-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlnms_neighbors.py
135 lines (99 loc) · 4.17 KB
/
lnms_neighbors.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/usr/bin/python3
# LibreNMS Neighbor Discovery Script
#
# @author Skylark (github.com/LoveSkylark)
# @license GPL
import os
import sys
import logging.handlers
import argparse
from dotenv import load_dotenv
from Libs.LibreNMSAPIClient.LibreNMSAPIClient import LibreNMSAPIClient
def setup_logging(log_file):
log_dir = os.path.join('..', os.environ.get('log_dir', 'var/log/'))
os.makedirs(log_dir, exist_ok=True)
log_file = os.path.join(log_dir, log_file)
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s:%(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
handlers=[
logging.handlers.RotatingFileHandler(
log_file,
maxBytes=5*1024*1024,
backupCount=10
)
]
)
def parse_args():
parser = argparse.ArgumentParser(description="Script to download LibreNMS configuration")
parser.add_argument("hostname", nargs="?", help="Hostname to filter on")
return parser.parse_args()
def print_help(args):
if not args.hostname:
print()
print("Add hostname to narrow list")
print("Examples:")
print(" ./lnms_neighbors.py 'partial-or-full-hostname'")
# -------
def get_api_data(lnms):
try:
devices = lnms.list_devices()
links = lnms.list_links()
ports = lnms.get_all_ports()
except Exception as e:
logging.error(f"Error calling API: {e}")
sys.exit(1)
logging.info("API call succeeded")
return devices, links, ports
def list_unknown_neighbors(args, devices, links, ports):
neighbours = find_unknown_neighbors(devices, links)
# Get the list of unknown neighbors
for neighbour in neighbours:
logging.info(f"Neighbour {neighbour} discovered")
# If no hostname argument is given, print all unknown neighbors
if not args.hostname:
print(neighbour)
# If a hostname argument is given, print matching neighbors and their port information
elif neighbour.startswith(args.hostname):
print(neighbour)
for device_name, port_name in get_sorted_port_list(args.hostname, devices, links, ports):
print(f" -> {device_name} ({port_name})")
def find_unknown_neighbors(devices, links):
# Create a set of all local and remote device short names in lowercase
local_match = set(i['sysName'].lower().split('.', 1)[0] for i in devices if isinstance(i, dict))
remote_match = set(i['remote_hostname'].lower().split('(', 1)[0].split('.', 1)[0] for i in links if isinstance(i, dict))
# Compute the set difference between the two sets to find remote hostnames that don't have a matching local device name
reply = sorted(list(remote_match - local_match))
return reply
def get_sorted_port_list(hostname, devices, links, ports):
reply = []
for link in links:
# Check if the remote hostname of the link matches the specified hostname
if hostname in link['remote_hostname'].lower().split('.', 1)[0]:
# Retrieve the device name associated with the local device ID of the link
device_name = next((device['sysName'] for device in devices if device['device_id'] == link['local_device_id']), None)
# Retrieve the port name associated with the local port ID of the link
port_name = next((port['ifName'] for port in ports if port['port_id'] == link['local_port_id']), None)
reply.append((device_name, port_name))
# Sort the 'reply' list by the device name in ascending order (case-insensitive)
reply.sort(key=lambda x: x[0].lower() if x[0] else '')
return reply
def main():
# Load environment variables
load_dotenv()
# Setup logging
log_file = "lnms_neighbors.log"
setup_logging(log_file)
# Parse command line arguments
args = parse_args()
# Create API client
lnms = LibreNMSAPIClient()
# Get data from API
devices, links, ports = get_api_data(lnms)
# Print results
list_unknown_neighbors(args, devices, links, ports)
# Print help text
print_help(args)
if __name__ == "__main__":
main()