image

Med Merakis API kan en automatisera alla möjliga saker, från att lista sina enheter till att skapa konfiguration eller t.o.m. skapa helt nya organisationer och nätverk på ett standardiserat sätt.

I det här inlägget tänker jag visa hur enkelt det är att komma igång och visa ett enkelt Pythonscript som låter användaren välja organisation och nätverk för att sedan lista enheterna i det valda nätverket.

Men vi tar det från början…

Aktivera API för din organisation

Det första som behöver göras är att aktivera API för organisationen under “Organization > Settings > Dashboard API access”. Därefter behöver varje användare skapa sin egna unika API-nyckel i inställningarna för sin profil. Kom ihåg att spara din API-nyckel på ett säkert sätt, så att ingen annan kan missbruka den!

För enkelhetens skull kommer jag använda mig av en offentlig API-nyckel som ger läsrättigheter till en DevNet-miljö.

Merakis pythonmodul

Meraki tillhandahåller en pythonmodul så vi slipper konstruera egna REST requests. Installera den på din maskin med pip install meraki. Importera sedan modulen i dina script med import meraki.

Dokumentation för pythonmodulen hittar du här: Cisco Meraki - Python Library

Ett första test

>>> import meraki
# Sätt variabeln API_KEY (Hårdkoda aldrig din API-nyckel på detta sätt i riktig kod)
>>> API_KEY = '6bec40cf957de430a6f1f2baa056b99a4fac9ea0'
# Skapa en Dashboard-client
>>> dashboard = meraki.DashboardAPI(API_KEY)
2023-01-14 11:16:12       meraki:     INFO > Meraki dashboard API session initialized with these parameters: {'version': '1.27.0', 'api_key': '************************************9ea0', 'base_url': 'https://api.meraki.com/api/v1', 'single_request_timeout': 60, 'certificate_path': '', 'requests_proxy': '', 'wait_on_rate_limit': True, 'nginx_429_retry_wait_time': 60, 'action_batch_retry_wait_time': 60, 'retry_4xx_error': False, 'retry_4xx_error_wait_time': 60, 'maximum_retries': 2, 'simulate': False, 'be_geo_id': None, 'caller': None, 'use_iterator_for_get_pages': False}
# För att bli av med loggen skickar jag också med parametern 'suppress_logging=True'
>>> dashboard = meraki.DashboardAPI(API_KEY, suppress_logging=True)
# Hämta en lista av tillgängliga organisationer
>>> orgs = dashboard.organizations.getOrganizations()
# Skriv ut organisationerna (En lista som innehåller en eller flera dictionaries)
>>> print(orgs)
[{'id': '463308', 'name': 'Hi Cory', 'url': 'https://n18.meraki.com/o/vB2D8a/manage/organization/overview', 'api': {'enabled': True}, 'licensing': {'model': 'per-device'}, 'cloud': {'region': {'name': 'North America'}}, 'management': {'details': []}}, {'id': '573083052582915028', 'name': 'New Meraki Org', 'url': 'https://n18.meraki.com/o/PoiDucs/manage/organization/overview', 'api': {'enabled': True}, 'licensing': {'model': 'co-term'}, 'cloud': {'region': {'name': 'North America'}}, 'management': {'details': []}}]
# Egentligen över 30 organisationer, men jag har kapat outputen.

I testet ovan har vi gjort våra första API-anrop mot Meraki och fått tillbaka en lista med tillgängliga organisationer. I det här fallet finns det över 30 organisationer att välja på. Om du har en egen Merakimiljö är chansen stor att det bara finns en eller några enstaka organisationer.

Hämta mer information

För varje organisation får vi en massa information som vi i nuläget inte bryr oss om. Den information vi behöver för att gå vidare är egentligen bara ‘id’, men eftersom dom flesta av oss är människor använder vi namnet för att identifiera en organisation. Vi kan också se om organisationen har aktiverat användandet av API.

I exemplet nedan loopar vi igenom alla organisationer och skriver ut ID, Namn och API-status.

>>> for org in orgs:
...   print(f"ID: {org['id']}, Name: {org['name']}, API: {org['api']['enabled']}")
...
ID: 463308, Name: Hi Cory, API: True
ID: 573083052582915028, Name: New Meraki Org, API: True
ID: 865776, Name: Cisco Live US 2019, API: True
ID: 681155, Name: DeLab, API: True
ID: 566327653141842188, Name: DevNetAssoc, API: True
ID: 575334852396582591, Name: My Org, API: True
ID: 575334852396582684, Name: SVR, API: True
ID: 575334852396582738, Name: My organization, API: True
ID: 575334852396582755, Name: Your Organization, API: False
ID: 575334852396582756, Name: Personal.Lekhnath, API: True
ID: 575334852396582973, Name: DevNet Test Org, API: True
ID: 575334852396582986, Name: DevNet Test Org, API: True
ID: 575334852396583031, Name: My organization, API: True
ID: 575334852396583051, Name: Hi Cory, API: True
ID: 575334852396583071, Name: PM_Test, API: True
ID: 575334852396583093, Name: DevRelx23, API: True
ID: 575334852396583128, Name: gk, API: True
ID: 575334852396583131, Name: thienbao, API: True
ID: 575334852396583133, Name: Hi Cory, API: True
ID: 575334852396583134, Name: Wotan, API: True
ID: 575334852396583158, Name: abcdefg, API: True
ID: 575334852396583197, Name: Sample Org, API: True
ID: 575334852396583213, Name: sample_network, API: False
ID: 575334852396583237, Name: changetest, API: True
ID: 575334852396583264, Name: DevRelations, API: True
ID: 575334852396583536, Name: TNF - The Network Factory, API: True
ID: 575334852396583708, Name: helloworld, API: True
ID: 575334852396583819, Name: test5, API: True
ID: 52636, Name: Forest City - Other, API: True
ID: 573083052582915144, Name: My organization, API: True
ID: 573083052582915143, Name: My organization - clone, API: True
ID: 573083052582914605, Name: Jacks_test_net, API: True
ID: 573083052582914233, Name: organization with name changed, API: True

Mycket lättare att identifiera våra organisationer nu!

Jag är intresserad av organisationen DeLab med ID 681155 och vill veta mer om den. Låt oss kika på vilka nätverk som huserar där!

# Sätt org_id till önskat id
>>> org_id = '681155'
# Anropa funktionen getOrganizationNetworks() för att få en lista med nätverk.
# Spara resultatet i 'networks'.
>>> networks = dashboard.organizations.getOrganizationNetworks(org_id)
>>> print(networks)
[{'id': 'L_566327653141843049', 'organizationId': '681155', 'name': 'Lyoli', 'productTypes': ['appliance', 'camera', 'switch', 'wireless'], 'timeZone': 'America/New_York', 'tags': [], 'enrollmentString': None, 'url': 'https://n392.meraki.com/Lyoli-switch/n/kjwRabg/manage/usage/list', 'notes': '', 'isBoundToConfigTemplate': False}, {'id': 'L_566327653141846927', 'organizationId': '681155', 'name': 'Vegas Apartment', 'productTypes': ['appliance', 'camera', 'switch', 'wireless'], 'timeZone': 'America/Los_Angeles', 'tags': [], 'enrollmentString': None, 'url': 'https://n392.meraki.com/Vegas-Apartment-/n/YreSWdg/manage/usage/list', 'notes': '', 'isBoundToConfigTemplate': False}, {'id': 'L_566327653141856854', 'organizationId': '681155', 'name': 'DNEAlertsNet', 'productTypes': ['appliance', 'camera', 'switch', 'wireless'], 'timeZone': 'America/Los_Angeles', 'tags': ['tag1', 'tag2'], 'enrollmentString': None, 'url': 'https://n392.meraki.com/DNEAlertsNet-swi/n/vUktkag/manage/usage/list', 'notes': '', 'isBoundToConfigTemplate': False}, {'id': 'L_783626335162466320', 'organizationId': '681155', 'name': 'DevNetLab', 'productTypes': ['appliance', 'camera', 'switch', 'wireless'], 'timeZone': 'America/Los_Angeles', 'tags': ['tag1'], 'enrollmentString': None, 'url': 'https://n392.meraki.com/DevNetLab-applia/n/xaNlkcig/manage/usage/list', 'notes': '', 'isBoundToConfigTemplate': False}, {'id': 'L_783626335162466514', 'organizationId': '681155', 'name': 'DevNetLab2', 'productTypes': ['appliance', 'cellularGateway', 'sensor', 'switch', 'wireless'], 'timeZone': 'America/Los_Angeles', 'tags': [], 'enrollmentString': None, 'url': 'https://n392.meraki.com/DevNetLab2-switc/n/selmycig/manage/usage/list', 'notes': '', 'isBoundToConfigTemplate': False}, {'id': 'L_783626335162466515', 'organizationId': '681155', 'name': 'DevNetLab3', 'productTypes': ['appliance', 'cellularGateway', 'sensor', 'switch', 'wireless'], 'timeZone': 'America/Los_Angeles', 'tags': [], 'enrollmentString': None, 'url': 'https://n392.meraki.com/DevNetLab3-wirel/n/e5u4ibig/manage/usage/list', 'notes': None, 'isBoundToConfigTemplate': False}, {'id': 'N_566327653141899127', 'organizationId': '681155', 'name': 'Nolan', 'productTypes': ['wireless'], 'timeZone': 'America/Los_Angeles', 'tags': [], 'enrollmentString': None, 'url': 'https://n392.meraki.com/Nolan/n/9qi_yag/manage/usage/list', 'notes': '', 'isBoundToConfigTemplate': False}, {'id': 'N_566327653141902646', 'organizationId': '681155', 'name': 'Lyoli MDM', 'productTypes': ['systemsManager'], 'timeZone': 'America/Los_Angeles', 'tags': [], 'enrollmentString': None, 'url': 'https://n392.meraki.com/Lyoli-MDM/n/-JaAJcg/manage/usage/list', 'notes': None, 'isBoundToConfigTemplate': False}]

# Loopa igenom listan och skriv ut ID & Namn.
>>> for network in networks:
...   print('ID:', network['id'], 'Name:', network['name'])
...
ID: L_566327653141843049 Name: Lyoli
ID: L_566327653141846927 Name: Vegas Apartment
ID: L_566327653141856854 Name: DNEAlertsNet
ID: L_783626335162466320 Name: DevNetLab
ID: L_783626335162466514 Name: DevNetLab2
ID: L_783626335162466515 Name: DevNetLab3
ID: N_566327653141899127 Name: Nolan
ID: N_566327653141902646 Name: Lyoli MDM

Ok, vi har 8st nätverk i vår organisation. Låt oss kika på vilka enheter vi har i nätverket DevNetLab .

För att göra det använder jag funktionen getOrganizationDevicesStatuses(), jag skickar med parametrar för att filtrera på organisation och nätverk.

# Sätt net_id till önskat id.
>>> net_id = 'L_783626335162466320'
>>> deviceStatuses = dashboard.organizations.getOrganizationDevicesStatuses(
...     org_id,networkIds=net_id)
>>> print(deviceStatuses)
[{'name': 'ms01-dl1', 'serial': 'Q2HP-EC87-M9B8', 'mac': 'e0:55:3d:d0:04:c5', 'publicIp': '76.250.206.183', 'networkId': 'L_783626335162466320', 'status': 'online', 'lastReportedAt': '2023-01-14T11:29:16.985000Z', 'productType': 'switch', 'components': {'powerSupplies': []}, 'model': 'MS220-8P', 'tags': ['recently-added'], 'lanIp': '192.168.128.2', 'gateway': '192.168.128.1', 'ipType': 'dhcp', 'primaryDns': '192.168.128.1', 'secondaryDns': None}, {'name': 'ap01-dl1', 'serial': 'Q2LD-FGN3-VP7S', 'mac': '0c:8d:db:b2:77:f8', 'publicIp': '76.250.206.183', 'networkId': 'L_783626335162466320', 'status': 'online', 'lastReportedAt': '2023-01-14T11:29:49.445000Z', 'productType': 'wireless', 'model': 'MR52', 'tags': [], 'lanIp': '192.168.128.7', 'gateway': '192.168.128.1', 'ipType': 'dhcp', 'primaryDns': '192.168.128.1', 'secondaryDns': None}, {'name': 'mx01-dl1', 'serial': 'Q2QN-Q6EY-NP7J', 'mac': '0c:8d:db:b0:c2:dc', 'publicIp': '76.250.206.183', 'networkId': 'L_783626335162466320', 'status': 'online', 'lastReportedAt': '2023-01-14T11:29:22.027000Z', 'productType': 'appliance', 'components': {'powerSupplies': []}, 'model': 'MX65', 'tags': [], 'usingCellularFailover': False, 'wan1Ip': '192.168.128.102', 'wan1Gateway': '192.168.128.1', 'wan1IpType': 'dhcp', 'wan1PrimaryDns': '192.168.128.1', 'wan1SecondaryDns': None, 'wan2Ip': None}]

# Loopa igenom listan och skriv ut Namn, Modell & Status.
>>> for status in deviceStatuses:
...   print(f"Name: {status['name']}, Model: {status['model']}, Status: {status['status']}")
...
Name: ms01-dl1, Model: MS220-8P, Status: online
Name: ap01-dl1, Model: MR52, Status: online
Name: mx01-dl1, Model: MX65, Status: online

Vi har nu lärt oss att med hjälp av API-anrop välja en tillgänglig organisation, ett lämpligt nätverk och att lista enheterna i ett nätverk!

Förenkla med script

Exemplen ovan körs direkt i Pythontolken och kräver en del kopierande och klistrande, inte så smidigt om det ska göras om och om igen.

Jag har därför skrivit ett enkelt script som använder samma funktioner som vi redan sett, men istället för att hårdkoda API-nyckeln får användaren ange den. För att sedan välja organisation och nätverk listar vi möjliga val och ber användaren bestämma.

När vi kör scriptet ser det ut såhär:

Expandera
$python3 api-intro.py
> Specify Meraki API key : 6bec40cf957de430a6f1f2baa056b99a4fac9ea0
*** Multiple Organizations found! ***
INDEX: 0, Name: Cisco Live US 2019, API: True
INDEX: 1, Name: New Meraki Org, API: True
INDEX: 2, Name: Hi Cory, API: True
INDEX: 3, Name: DeLab, API: True
INDEX: 4, Name: DevNetAssoc, API: True
INDEX: 5, Name: My Org, API: True
INDEX: 6, Name: SVR, API: True
INDEX: 7, Name: My organization, API: True
INDEX: 8, Name: Your Organization, API: False
INDEX: 9, Name: Personal.Lekhnath, API: True
INDEX: 10, Name: DevNet Test Org, API: True
INDEX: 11, Name: DevNet Test Org, API: True
INDEX: 12, Name: My organization, API: True
INDEX: 13, Name: Hi Cory, API: True
INDEX: 14, Name: PM_Test, API: True
INDEX: 15, Name: DevRelx23, API: True
INDEX: 16, Name: gk, API: True
INDEX: 17, Name: thienbao, API: True
INDEX: 18, Name: Hi Cory, API: True
INDEX: 19, Name: Wotan, API: True
INDEX: 20, Name: abcdefg, API: True
INDEX: 21, Name: Sample Org, API: True
INDEX: 22, Name: sample_network, API: False
INDEX: 23, Name: changetest, API: True
INDEX: 24, Name: DevRelations, API: True
INDEX: 25, Name: TNF - The Network Factory, API: True
INDEX: 26, Name: helloworld, API: True
INDEX: 27, Name: test5, API: True
INDEX: 28, Name: Forest City - Other, API: True
INDEX: 29, Name: My organization, API: True
INDEX: 30, Name: My organization - clone, API: True
INDEX: 31, Name: Jacks_test_net, API: True
INDEX: 32, Name: organization with name changed, API: True
> Specify Organization by INDEX : 3
 Selected Organization: Name = DeLab, ID = 681155
*** Multiple Networks found! ***
INDEX: 0, Name: Lyoli
INDEX: 1, Name: Vegas Apartment
INDEX: 2, Name: DNEAlertsNet
INDEX: 3, Name: DevNetLab
INDEX: 4, Name: DevNetLab2
INDEX: 5, Name: DevNetLab3
INDEX: 6, Name: Nolan
INDEX: 7, Name: Lyoli MDM
> Specify Network by INDEX : 3
 Selected Network: Name = DevNetLab, ID = L_783626335162466320
*** Status for devices in DevNetLab ***
Name: ms01-dl1, Model: MS220-8P, Status: online
Name: ap01-dl1, Model: MR52, Status: online
Name: mx01-dl1, Model: MX65, Status: online


Om du vill testa detta själv kan du kopiera koden nedanför:

Expandera
'''
api-intro.py
Short interactive script to print our Meraki device statuses.
Asks user to provide API key and select organisations and network if mutiple options exists.
'''

import meraki
import json

# DevNet API key '6bec40cf957de430a6f1f2baa056b99a4fac9ea0'

# Get API Key from user input
API_KEY = input('> Specify Meraki API key : ')
# Initiate dashboard, exit if it fails
try:
  dashboard = meraki.DashboardAPI(API_KEY, suppress_logging=True)
except Exception as e:
  print(f'Error occurred: {e}')
  exit(0)

# Get Meraki Orgs and have user choose if more than 1.
# Otherwise print which Org is used.
try:
  orgs = dashboard.organizations.getOrganizations()
except Exception as e:
  print(f'Error occurred: {e}')
  exit()

if len(orgs) > 1:
  i = 0
  print('*** Multiple Organizations found! ***')
  for org in orgs:
    print(f"INDEX: {i}, Name: {org['name']}, API: {org['api']['enabled']}")
    i=i+1
  org_id = int(input('> Specify Organization by INDEX : '))
  if org_id >= 0 and org_id < len(orgs):
    print(f" Selected Organization: Name = {orgs[org_id]['name']}, ID = {orgs[org_id]['id']}")
    org_id=orgs[org_id]['id']
  else:
    print(f"Invalid INDEX: {org_id}")
    exit(0)
elif len(orgs) == 1:
  print(f"Using Meraki Org : {orgs[0]['name']}, {orgs[0]['id']}")
  org_id = orgs[0]['id']

# Get networks and have user choose if more than 1.
try:
  networks = dashboard.organizations.getOrganizationNetworks(org_id)
except Exception as e:
  print(f'Error occurred: {e}')
  exit()

if len(networks) > 1:
  i=0
  print('*** Multiple Networks found! ***')
  for network in networks:
    #print('ID:', networkId['id'], 'Name:', networkId['name'])
    print(f"INDEX: {i}, Name: {network['name']}")
    i=i+1
  net_id = int(input('> Specify Network by INDEX : '))
  if net_id >= 0 and net_id < len(networks):
    print(f" Selected Network: Name = {networks[net_id]['name']}, ID = {networks[net_id]['id']}")
    net_id=networks[net_id]['id']
  else:
    print(f"Invalid INDEX: {net_id}")
    exit(0)
elif len(networks) == 1:
    print(f"Using Meraki Network : {networks[0]['name']}, {networks[0]['id']}")
    net_id = networks[0]['id']

# Get network information
network = dashboard.networks.getNetwork(net_id)
# Print status for devices in network.
deviceStatuses = dashboard.organizations.getOrganizationDevicesStatuses(
    org_id,networkIds=net_id, total_pages='all'
)
#print(json.dumps(deviceStatuses, indent=2))

print(f"*** Status for devices in {network['name']} ***")
for status in deviceStatuses:
  print(f"Name: {status['name']}, Model: {status['model']}, Status: {status['status']}")

# Uncomment below to print more information about network and devices
'''
devices = dashboard.networks.getNetworkDevices(net_id)
print(f"Information for network {network['name']}:")
print(json.dumps(network, indent=2))
print(f"\nDevices in network {network['name']}:")
print(json.dumps(devices, indent=2))
'''

exit(0)

Sammanfattning

Tack vare Merakis pythonmodul och dokumentation är det ganska enkelt att komma igång och använda deras API. Med grunderna ovan och API-dokumentationen kan en börja utforska vilken information som finns tillgänglig att hämta från ens egna organisation och nätverk.

Länkar

Meraki API dokumentation


Senior Consultant

2025

Acebit expanderar

1 minute read

Acebit expanderar – automationsess från Dalarna öppnar i Stockholm

Back to Top ↑

2024

Acebit i Falu-Kuriren

less than 1 minute read

Även Falu-Kuriren har intresserat sig för Acebit och besökt oss i Falun!

Back to Top ↑

2023

Meraki API & Mgmt interface

4 minute read

Nyligen stötte jag på ett scenario som innebar att ca 200 Meraki-enheter behövde byta inställning från DHCP till statisk IP-adressering. Istället för att gör...

Arbeta med VPC Del3 - Konfiguration

3 minute read

I mina tidigare inlägg om virtuella port-channels kikade vi på vad det är och vilka delar de utgör. Det här avsnittet kommer beröra hur en grundkonfiguration...

Få upp farten med concurrency

3 minute read

Bakgrund Idag tänkt jag skriva några rader om att skriva concurrent kod, eller “samtidighet” om vi prompt ska översätta det till svenska. För att enklare för...

Back to Top ↑

2022

Back to Top ↑

2021

Back to Top ↑