#!/usr/bin/env python3
import meraki
import argparse
import sys
import os
def print_nei(device):
"""
Print device neighbor information
"""
for port, port_data in device.get("ports", {}).items():
for proto, nei in port_data.items():
ip = nei.get("address", nei.get("managementAddress"))
if proto == "cdp" and protocol != "lldp":
system_name = nei.get("deviceId", "noname")
print(
f'CDP LOCAL {name[:24]:24} SOURCE-PORT {nei.get("sourcePort"):8} REMOTE DEVICE {system_name.split(".")[0][:40]:40} REMOTE PORT {nei.get("portId"):24} REMOTE IP {ip}'
)
elif proto == "lldp" and protocol != "cdp":
system_name = nei.get("systemName", "noname")
print(
f'LLDP LOCAL {name[:24]:24} SOURCE-PORT {nei.get("sourcePort"):8} REMOTE DEVICE {system_name.split(".")[0][:40]:40} REMOTE PORT {nei.get("portId"):24} REMOTE IP {ip}'
)
def get_id_name(object_id, object_list):
"""
Find object name and ID if object exists
Returns ID and NAME
"""
filtered_objects = [
o
for o in object_list
if o.get("name") == object_id or o.get("id") == object_id
]
if filtered_objects:
return filtered_objects[0].get("id"), filtered_objects[0].get("name")
return None, None
def main():
# Getting arguments
parser = argparse.ArgumentParser()
parser.add_argument(
"-K",
"--apikey",
help="Meraki dashboard API key or set env var",
type=str,
required=False,
)
parser.add_argument(
"-O", "--organization", help="organization ID or NAME", type=str, required=False
)
parser.add_argument("-N", "--network", help="network", type=str, required=False)
parser.add_argument(
"-P",
"--protocol",
help="filter protocol",
type=str,
choices=["cdp", "lldp"],
default="",
required=False,
)
parser.add_argument(
"-A",
"--all",
help="print information for all networks in organization",
dest="all",
action="store_true",
default=False,
required=False,
)
args = parser.parse_args()
organization = args.organization
protocol = args.protocol
# Verify API key is provided
if args.apikey:
apikey = args.apikey
else:
apikey = os.environ.get("apikey")
if not apikey:
print
("\nERROR: MISSING MERAKI DASHBOARD API KEY IN ARGUMENTS AND ENV VAR\n")
sys.exit()
# Verify API key is valid and get organizations
try:
dashboard = meraki.DashboardAPI(
api_key=apikey, print_console=False, output_log=False, suppress_logging=True
)
organizations = dashboard.organizations.getOrganizations()
except meraki.APIError as e:
print(f"\nERROR GETTING ORGANIZATIONS: {e}\n")
sys.exit()
# If no organization is provided, print the list of organizations
if not organization:
print("\nORGANIZATIONS AVAILABLE\n")
for org in organizations:
print(f"NAME: {org.get('name'):40} ID: {org.get('id'):20}")
sys.exit()
org_id, org_name = get_id_name(organization, organizations)
if not org_id:
print(f"\nERROR: ORGANIZATION {organization} NOT FOUND\n")
sys.exit()
networks = dashboard.organizations.getOrganizationNetworks(org_id)
# If a specific network is provided, print its neighbors
if args.network:
network_id, network_name = get_id_name(args.network, networks)
if not network_id:
print(f"\nERROR: NETWORK {args.network} NOT FOUND\n")
sys.exit()
devices = dashboard.networks.getNetworkDevices(network_id)
for device in devices:
serial, name = device.get("serial"), device.get("name", "MISSING")
print_nei(device)
else:
if not args.all:
print(
f'\nNETWORKS AVAILABLE FOR ORGANIZATION "{org_name}" with ID {org_id}\n'
)
for net in networks:
print(f"NETWORK: {net.get('name'):50} ID: {net.get('id'):20}")
else:
for net in networks:
network_id = net.get("id")
devices = dashboard.networks.getNetworkDevices(network_id)
for device in devices:
serial, name = device.get("serial"), device.get("name", "MISSING")
print_nei(device)
if __name__ == "__main__":
main()