Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update routeros_facts #101

Merged
merged 32 commits into from
Aug 21, 2020
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
e186983
Update routeros_facts.py
adeptvin1 Aug 14, 2020
da8dca6
Update routeros_facts.py
adeptvin1 Aug 14, 2020
18bb90b
Update plugins/modules/network/routeros/routeros_facts.py
adeptvin1 Aug 15, 2020
60cf2f6
Update plugins/modules/network/routeros/routeros_facts.py
adeptvin1 Aug 15, 2020
03d05d1
Update plugins/modules/network/routeros/routeros_facts.py
adeptvin1 Aug 15, 2020
f60b518
Update plugins/modules/network/routeros/routeros_facts.py
adeptvin1 Aug 15, 2020
9fe9561
Update plugins/modules/network/routeros/routeros_facts.py
adeptvin1 Aug 15, 2020
db26399
Update plugins/modules/network/routeros/routeros_facts.py
adeptvin1 Aug 15, 2020
c304316
Update plugins/modules/network/routeros/routeros_facts.py
adeptvin1 Aug 15, 2020
8a55bac
Update plugins/modules/network/routeros/routeros_facts.py
adeptvin1 Aug 15, 2020
93d331c
Update plugins/modules/network/routeros/routeros_facts.py
adeptvin1 Aug 15, 2020
74cbc76
Update plugins/modules/network/routeros/routeros_facts.py
adeptvin1 Aug 15, 2020
10dcee3
Create 101_update_routeros_facts.yml
adeptvin1 Aug 15, 2020
b9fd967
Update plugins/modules/network/routeros/routeros_facts.py
adeptvin1 Aug 15, 2020
0e7b46c
Update changelogs/fragments/101_update_routeros_facts.yml
adeptvin1 Aug 16, 2020
ee1f714
add test default function
adeptvin1 Aug 20, 2020
119375c
add test data
adeptvin1 Aug 20, 2020
50fbd8d
Update routing_ospf_neighbor_print_detail_without-paging
adeptvin1 Aug 20, 2020
8b807c2
add test function "Routing"
adeptvin1 Aug 20, 2020
daa78ab
added information of version
adeptvin1 Aug 20, 2020
0e21f70
Removed extra spaces
adeptvin1 Aug 20, 2020
dbec1f3
add one more version, "ansible_net_cpu_load"
adeptvin1 Aug 20, 2020
c8da8c2
remove many blank lines
adeptvin1 Aug 20, 2020
4e51019
remove 'too many blank lines'
adeptvin1 Aug 20, 2020
5e1baa1
renamed arhitec to arch
adeptvin1 Aug 20, 2020
7c0395f
Update routeros_facts.py
adeptvin1 Aug 20, 2020
5925e00
Update test_routeros_facts.py
adeptvin1 Aug 20, 2020
7f77097
Update test_routeros_facts.py
adeptvin1 Aug 20, 2020
7495f87
one more
adeptvin1 Aug 20, 2020
b87cf2a
remove one route
adeptvin1 Aug 20, 2020
121bbf2
Update test_routeros_facts.py
adeptvin1 Aug 20, 2020
8a8e408
remove one neighbor
adeptvin1 Aug 20, 2020
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
2 changes: 2 additions & 0 deletions changelogs/fragments/101_update_routeros_facts.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- routeros_facts - now also collecting data about BGP and OSPF (https://github.com/ansible-collections/community.network/pull/101).
238 changes: 236 additions & 2 deletions plugins/modules/network/routeros/routeros_facts.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,20 @@
description: The configured hostname of the device
returned: always
type: str
ansible_net_arch:
description: The CPU architecture of the device
returned: always
type: str
adeptvin1 marked this conversation as resolved.
Show resolved Hide resolved
version_added: 1.2.0
ansible_net_uptime:
description: The uptime of the device
returned: always
type: str
felixfontein marked this conversation as resolved.
Show resolved Hide resolved
version_added: 1.2.0
ansible_net_cpu_load:
description: Current CPU load
returned: always
type: str
felixfontein marked this conversation as resolved.
Show resolved Hide resolved

# hardware
ansible_net_spacefree_mb:
Expand Down Expand Up @@ -110,6 +124,39 @@
description: The list of neighbors from the remote device
returned: when interfaces is configured
type: dict

# routing
ansible_net_bgp_peer:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is indented wrongly. There is a leading space which shouldn't be there. (That makes it invalid YAML.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I corrected it.

description: The dict bgp peer
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
description: The dict bgp peer
description: A dictionary that contains BGP peer data

returned: peer information
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

returned should contain the condition when this key is present in the output.

type: dict
version_added: 1.2.0
ansible_net_bgp_vpnv4_route:
description: A dictionary that contains BGP VPNv4 data
returned: vpnv4 route information
type: dict
version_added: 1.2.0
ansible_net_bgp_instance:
description: A dictionary that contains BGP instance data
returned: bgp instance information
type: dict
version_added: 1.2.0
ansible_net_route:
description: A dictionary that contains all routes from the routing table
returned: routes information in all routing table
type: dict
version_added: 1.2.0
ansible_net_ospf_instance:
description: A dictionary that contains OSPF instance data
returned: ospf instance information
type: dict
version_added: 1.2.0
ansible_net_ospf_neighbor:
description: A dictionary that contains OSPF neighbor data
returned: ospf neighbor information
type: dict
version_added: 1.2.0

"""
import re

Expand Down Expand Up @@ -148,11 +195,12 @@ def populate(self):
data = self.responses[0]
if data:
self.facts['hostname'] = self.parse_hostname(data)

data = self.responses[1]
if data:
self.facts['version'] = self.parse_version(data)

self.facts['architec'] = self.parse_architec(data)
self.facts['uptime'] = self.parse_uptime(data)
self.facts['cpu_load'] = self.parse_cpu_load(data)
data = self.responses[2]
if data:
self.facts['model'] = self.parse_model(data)
Expand All @@ -173,6 +221,21 @@ def parse_model(self, data):
if match:
return match.group(1)

def parse_architec(self, data):
match = re.search(r'architecture-name:\s(.*)\s*$', data, re.M)
if match:
return match.group(1)

def parse_uptime(self, data):
match = re.search(r'uptime:\s(.*)\s*$', data, re.M)
if match:
return match.group(1)

def parse_cpu_load(self, data):
match = re.search(r'cpu-load:\s(.*)\s*$', data, re.M)
if match:
return match.group(1)

def parse_serialnum(self, data):
match = re.search(r'serial-number:\s(.*)\s*$', data, re.M)
if match:
Expand Down Expand Up @@ -318,6 +381,177 @@ def parse_detail(self, data):
continue
yield parsed

class Routing(FactsBase):

COMMANDS = [
'/routing bgp peer print detail without-paging',
'/routing bgp vpnv4-route print detail without-paging',
'/routing bgp instance print detail without-paging',
'/ip route print detail without-paging',
'/routing ospf instance print detail without-paging',
'/routing ospf neighbor print detail without-paging'
]

DETAIL_RE = re.compile(r'([\w\d\-]+)=\"?(\w{3}/\d{2}/\d{4}\s\d{2}:\d{2}:\d{2}|[\w\d\-\.:/]+)')
WRAPPED_LINE_RE = re.compile(r'^\s+(?!\d)')


def populate(self):
super(Routing, self).populate()
self.facts['bgp_peer'] = dict()
self.facts['bgp_vpnv4_route'] = dict()
self.facts['bgp_instance'] = dict()
self.facts['route'] = dict()
self.facts['ospf_instance'] = dict()
self.facts['ospf_neighbor'] = dict()
data = self.responses[0]
if data:
peer = self.parse_bgp_peer(data)
self.populate_bgp_peer(peer)
data = self.responses[1]
if data:
vpnv4 = self.parse_vpnv4_route(data)
self.populate_vpnv4_route(vpnv4)
data = self.responses[2]
if data:
instance = self.parse_instance(data)
self.populate_bgp_instance(instance)

data = self.responses[3]
if data:
route = self.parse_route(data)
self.populate_route(route)

data = self.responses[4]
if data:
instance = self.parse_instance(data)
self.populate_ospf_instance(instance)

data = self.responses[5]
if data:
instance = self.parse_ospf_neighbor(data)
self.populate_ospf_neighbor(instance)

def preprocess(self, data):
preprocessed = list()
for line in data.split('\n'):
if len(line) == 0 or line[:5] == 'Flags':
continue
elif not re.match(self.WRAPPED_LINE_RE, line):
preprocessed.append(line)
else:
preprocessed[-1] += line
return preprocessed

def parse_name(self, data):
match = re.search(r'name=.(\S+\b)', data, re.M)
if match:
return match.group(1)

def parse_interface(self, data):
match = re.search(r'interface=([\w\d\-]+)', data, re.M)
if match:
return match.group(1)

def parse_instance_name(self, data):
match = re.search(r'instance=([\w\d\-]+)', data, re.M)
if match:
return match.group(1)


def parse_routing_mark(self, data):
match = re.search(r'routing-mark=([\w\d\-]+)', data, re.M)
if match:
return match.group(1)
else:
match = 'main'
return match

def parse_bgp_peer(self, data):
facts = dict()
data = self.preprocess(data)
for line in data:
name = self.parse_name(line)
facts[name] = dict()
for (key, value) in re.findall(self.DETAIL_RE, line):
facts[name][key] = value
return facts

def parse_instance(self, data):
facts = dict()
data = self.preprocess(data)
for line in data:
name = self.parse_name(line)
facts[name] = dict()
for (key, value) in re.findall(self.DETAIL_RE, line):
facts[name][key] = value
return facts

def parse_vpnv4_route(self, data):
facts = dict()
data = self.preprocess(data)
for line in data:
name = self.parse_interface(line)
facts[name] = dict()
for (key, value) in re.findall(self.DETAIL_RE, line):
facts[name][key] = value
return facts

def parse_route(self, data):
facts = dict()
data = self.preprocess(data)
for line in data:
name = self.parse_routing_mark(line)
facts[name] = dict()
for (key, value) in re.findall(self.DETAIL_RE, line):
facts[name][key] = value
return facts

def parse_ospf_instance(self, data):
facts = dict()
data = self.preprocess(data)
for line in data:
name = self.parse_name(line)
facts[name] = dict()
for (key, value) in re.findall(self.DETAIL_RE, line):
facts[name][key] = value
return facts

def parse_ospf_neighbor(self, data):
facts = dict()
data = self.preprocess(data)
for line in data:
name = self.parse_instance_name(line)
facts[name] = dict()
for (key, value) in re.findall(self.DETAIL_RE, line):
facts[name][key] = value
return facts


def populate_bgp_peer(self, data):
for key, value in iteritems(data):
self.facts['bgp_peer'][key] = value

def populate_vpnv4_route(self, data):
for key, value in iteritems(data):
self.facts['bgp_vpnv4_route'][key] = value

def populate_bgp_instance(self, data):
for key, value in iteritems(data):
self.facts['bgp_instance'][key] = value

def populate_route(self, data):
for key, value in iteritems(data):
self.facts['route'][key] = value

def populate_ospf_instance(self, data):
for key, value in iteritems(data):
self.facts['ospf_instance'][key] = value

def populate_ospf_neighbor(self, data):
for key, value in iteritems(data):
self.facts['ospf_neighbor'][key] = value


FACT_SUBSETS = dict(
default=Default,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Flags: X - disabled, A - active, D - dynamic,
C - connect, S - static, r - rip, b - bgp, o - ospf, m - mme,
B - blackhole, U - unreachable, P - prohibit
0 ADC dst-address=10.10.66.0/30 pref-src=10.10.66.1 gateway=bridge1
gateway-status=bridge1 reachable distance=0 scope=10
routing-mark=altegro

1 ADb dst-address=10.10.66.8/30 gateway=10.10.100.1
gateway-status=10.10.100.1 recursive via 10.10.1.2 GRE_TYRMA
distance=200 scope=40 target-scope=30 routing-mark=altegro
bgp-local-pref=100 bgp-origin=incomplete
bgp-ext-communities="RT:64520:666"

2 A S dst-address=0.0.0.0/0 gateway=85.15.75.109
gateway-status=85.15.75.109 reachable via Internet-VTK distance=1
scope=30 target-scope=10

3 ADC dst-address=10.10.1.0/30 pref-src=10.10.1.1 gateway=GRE_TYRMA
gateway-status=GRE_TYRMA reachable distance=0 scope=10

4 DC dst-address=10.10.1.4/30 pref-src=10.10.1.5 gateway=RB2011
gateway-status=RB2011 unreachable distance=255 scope=10

5 ADC dst-address=10.10.2.0/30 pref-src=10.10.2.1 gateway=VLAN_SAT.ROUTER
gateway-status=VLAN_SAT.ROUTER reachable distance=0 scope=10
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Flags: * - default, X - disabled
0 *X name="default" as=65530 router-id=0.0.0.0 redistribute-connected=no
redistribute-static=no redistribute-rip=no redistribute-ospf=no
redistribute-other-bgp=no out-filter="" client-to-client-reflection=yes
ignore-as-path-len=no routing-table=""

1 name="MAIN_AS_STARKDV" as=64520 router-id=10.10.50.1
redistribute-connected=no redistribute-static=no redistribute-rip=no
redistribute-ospf=no redistribute-other-bgp=no out-filter=""
client-to-client-reflection=yes ignore-as-path-len=no routing-table=""
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Flags: X - disabled, E - established
0 E name="iBGP_BRAS.TYRMA" instance=MAIN_AS_STARKDV remote-address=10.10.100.1
remote-as=64520 tcp-md5-key="" nexthop-choice=default multihop=no
route-reflect=yes hold-time=3m ttl=default in-filter="" out-filter=""
address-families=ip,l2vpn,vpnv4 update-source=LAN_KHV
default-originate=never remove-private-as=no as-override=no passive=no
use-bfd=yes

1 E name="iBGP_BRAS_SAT" instance=MAIN_AS_STARKDV remote-address=10.10.50.230
remote-as=64520 tcp-md5-key="" nexthop-choice=default multihop=no
route-reflect=yes hold-time=3m ttl=default in-filter="" out-filter=""
address-families=ip default-originate=never remove-private-as=no
as-override=no passive=no use-bfd=yes
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Flags: L - label-present
0 L route-distinguisher=64520:666 dst-address=10.10.66.8/30 gateway=10.10.100.1
interface=GRE_TYRMA in-label=6136 out-label=6136 bgp-local-pref=100
bgp-origin=incomplete bgp-ext-communities="RT:64520:666"

1 L route-distinguisher=64520:666 dst-address=10.10.66.0/30 interface=bridge1
in-label=1790 bgp-ext-communities="RT:64520:666"
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Flags: X - disabled, * - default
0 * name="default" router-id=10.10.50.1 distribute-default=never redistribute-connected=no
redistribute-static=no redistribute-rip=no redistribute-bgp=no redistribute-other-ospf=no
metric-default=1 metric-connected=20 metric-static=20 metric-rip=20 metric-bgp=auto
metric-other-ospf=auto in-filter=ospf-in out-filter=ospf-out

1 name="OSPF_ALTEGRO" router-id=10.10.66.1 distribute-default=never redistribute-connected=no
redistribute-static=no redistribute-rip=no redistribute-bgp=no redistribute-other-ospf=no
metric-default=1 metric-connected=20 metric-static=20 metric-rip=20 metric-bgp=auto
metric-other-ospf=auto in-filter=ospf-in out-filter=ospf-out routing-table=altegro
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
0 instance=default router-id=10.10.100.1 address=10.10.1.2 interface=GRE_TYRMA priority=1
dr-address=0.0.0.0 backup-dr-address=0.0.0.0 state="Full" state-changes=15 ls-retransmits=0
ls-requests=0 db-summaries=0 adjacency=6h8m46s

1 instance=default router-id=10.10.50.230 address=10.10.50.230 interface=VLAN_TECH_LAN prior
dr-address=10.10.50.230 backup-dr-address=10.10.50.218 state="Full" state-changes=6
ls-retransmits=0 ls-requests=0 db-summaries=0 adjacency=4w6d10h47m53s
Loading