16 KiB
To help you get started with using the Meraki Dashboard API in a sandbox environment, I'll provide you with a project structure and an example script that you can use as a template. This project folder will include a sample Python script, a configuration for environment variables, and instructions for running the script.
Project Folder Structure
automation-scripts/
├── README.md
├── scripts/
│ ├── clientcount.py
│ ├── get_license.py
│ └── inventorycsv.py
├── requirements.txt
└── setup_env.sh
README.md
Meraki Dashboard API Automation Scripts
This project contains Python scripts for automating tasks with the Meraki Dashboard API.
Prerequisites
- Python 3.x
- Meraki API Key
- Required Python packages (listed in
requirements.txt)
Setup
-
Clone this repository.
-
Install the required Python packages:
pip install -r requirements.txt -
Set up your environment variables by sourcing the
setup_env.shfile:source setup_env.sh
Running Scripts
Get Client Count
python scripts/clientcount.py -k $MERAKI_DASHBOARD_API_KEY -o "DeLab"
Get License Information
python scripts/get_license.py -k $MERAKI_DASHBOARD_API_KEY -o "DeLab"
Get Inventory List
python scripts/inventorycsv.py -k $MERAKI_DASHBOARD_API_KEY -o "DeLab" -f DeLab_inventory_list.csv
Notes
Make sure to check each script's usage information in the header of the script.
requirements.txt
requests
pyyaml
pymongo
pysnmp
meraki
setup_env.sh
#!/bin/bash
# Set your Meraki API key here
export MERAKI_DASHBOARD_API_KEY="d03190ff333a3c7feaed89fec5b3b2529f59e8ec"
scripts/clientcount.py
import requests
import argparse
def get_client_count(api_key, org_name):
base_url = 'https://api.meraki.com/api/v1'
headers = {
'Authorization': f'Bearer {api_key}'
}
# Get the list of organizations
orgs_response = requests.get(f'{base_url}/organizations', headers=headers)
orgs = orgs_response.json()
# Find the organization ID for the given name
org_id = None
for org in orgs:
if org['name'] == org_name:
org_id = org['id']
break
if org_id is None:
print(f'Organization {org_name} not found')
return
# Get the list of networks in the organization
networks_response = requests.get(f'{base_url}/organizations/{org_id}/networks', headers=headers)
networks = networks_response.json()
# Count the number of unique clients across all networks
unique_clients = set()
for network in networks:
network_id = network['id']
clients_response = requests.get(f'{base_url}/networks/{network_id}/clients', headers=headers)
clients = clients_response.json()
for client in clients:
unique_clients.add(client['mac'])
print(f'Total unique client MAC addresses across all WLAN APs: {len(unique_clients)}')
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Get client count for a Meraki organization')
parser.add_argument('-k', '--api_key', required=True, help='Meraki API key')
parser.add_argument('-o', '--org_name', required=True, help='Meraki organization name')
args = parser.parse_args()
get_client_count(args.api_key, args.org_name)
scripts/get_license.py
import requests
import argparse
def get_license_info(api_key, org_name):
base_url = 'https://api.meraki.com/api/v1'
headers = {
'Authorization': f'Bearer {api_key}'
}
# Get the list of organizations
orgs_response = requests.get(f'{base_url}/organizations', headers=headers)
orgs = orgs_response.json()
# Find the organization ID for the given name
org_id = None
for org in orgs:
if org['name'] == org_name:
org_id = org['id']
break
if org_id is None:
print(f'Organization {org_name} not found')
return
# Get the license information for the organization
license_response = requests.get(f'{base_url}/organizations/{org_id}/licenses', headers=headers)
license_info = license_response.json()
print(f'License info for organization "{org_name}" (ID: {org_id})')
print(f'Status: {license_info["status"]}')
print(f'Expiration date: {license_info["expirationDate"]}')
print('Licensed device counts:')
for license in license_info['licenses']:
print(f'{license["productType"]}:\t{license["total"]}')
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Get license info for a Meraki organization')
parser.add_argument('-k', '--api_key', required=True, help='Meraki API key')
parser.add_argument('-o', '--org_name', required=True, help='Meraki organization name')
args = parser.parse_args()
get_license_info(args.api_key, args.org_name)
scripts/inventorycsv.py
import requests
import csv
import argparse
def get_inventory(api_key, org_name, filename):
base_url = 'https://api.meraki.com/api/v1'
headers = {
'Authorization': f'Bearer {api_key}'
}
# Get the list of organizations
orgs_response = requests.get(f'{base_url}/organizations', headers=headers)
orgs = orgs_response.json()
# Find the organization ID for the given name
org_id = None
for org in orgs:
if org['name'] == org_name:
org_id = org['id']
break
if org_id is None:
print(f'Organization {org_name} not found')
return
# Get the inventory for the organization
inventory_response = requests.get(f'{base_url}/organizations/{org_id}/inventory/devices', headers=headers)
inventory = inventory_response.json()
# Write the inventory to a CSV file
with open(filename, 'w', newline='') as csvfile:
fieldnames = ['serial', 'model', 'networkId', 'mac', 'claimedAt']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
for device in inventory:
writer.writerow(device)
print(f'Inventory for organization "{org_name}" saved to {filename}')
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Get inventory for a Meraki organization')
parser.add_argument('-k', '--api_key', required=True, help='Meraki API key')
parser.add_argument('-o', '--org_name', required=True, help='Meraki organization name')
parser.add_argument('-f', '--filename', required=True, help='Output CSV file')
args = parser.parse_args()
get_inventory(args.api_key, args.org_name, args.filename)
Instructions for Running the Project
- Clone the repository:
git clone https://github.com/yourusername/automation-scripts.git
cd automation-scripts
- Install required Python packages:
pip install -r requirements.txt
- Set up environment variables:
source setup_env.sh
- Run the scripts:
-
Get client count:
python scripts/clientcount.py -k $MERAKI_DASHBOARD_API_KEY -o "DeLab" -
Get license information:
python scripts/get_license.py -k $MERAKI_DASHBOARD_API_KEY -o "DeLab" -
Get inventory list:
python scripts/inventorycsv.py -k $MERAKI_DASHBOARD_API_KEY -o "DeLab" -f DeLab_inventory_list.csv
This setup should give you a good starting point for working with the Meraki Dashboard API in a sandbox environment. If you have any further questions or need additional examples, feel free to ask!
Certainly! Let's add the retry mechanism to the get_license.py and inventorycsv.py scripts as well.
Updated get_license.py Script with Retry Mechanism
import requests
import argparse
import time
def get_license_info(api_key, org_name):
base_url = 'https://api.meraki.com/api/v1'
headers = {
'Authorization': f'Bearer {api_key}'
}
def make_request(url):
retries = 5
for i in range(retries):
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.json()
elif response.status_code == 429:
print(f"API rate limit exceeded. Retrying in {2 ** i} seconds...")
time.sleep(2 ** i)
else:
print(f"Error: {response.status_code} - {response.text}")
return None
return None
# Get the list of organizations
orgs = make_request(f'{base_url}/organizations')
if orgs is None:
return
# Find the organization ID for the given name
org_id = None
for org in orgs:
if org['name'] == org_name:
org_id = org['id']
break
if org_id is None:
print(f'Organization {org_name} not found')
return
# Get the license information for the organization
license_info = make_request(f'{base_url}/organizations/{org_id}/licenses')
if license_info is None:
return
print(f'License info for organization "{org_name}" (ID: {org_id})')
print(f'Status: {license_info["status"]}')
print(f'Expiration date: {license_info["expirationDate"]}')
print('Licensed device counts:')
for license in license_info['licenses']:
print(f'{license["productType"]}:\t{license["total"]}')
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Get license info for a Meraki organization')
parser.add_argument('-k', '--api_key', required=True, help='Meraki API key')
parser.add_argument('-o', '--org_name', required=True, help='Meraki organization name')
args = parser.parse_args()
get_license_info(args.api_key, args.org_name)
Updated inventorycsv.py Script with Retry Mechanism
import requests
import csv
import argparse
import time
def get_inventory(api_key, org_name, filename):
base_url = 'https://api.meraki.com/api/v1'
headers = {
'Authorization': f'Bearer {api_key}'
}
def make_request(url):
retries = 5
for i in range(retries):
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.json()
elif response.status_code == 429:
print(f"API rate limit exceeded. Retrying in {2 ** i} seconds...")
time.sleep(2 ** i)
else:
print(f"Error: {response.status_code} - {response.text}")
return None
return None
# Get the list of organizations
orgs = make_request(f'{base_url}/organizations')
if orgs is None:
return
# Find the organization ID for the given name
org_id = None
for org in orgs:
if org['name'] == org_name:
org_id = org['id']
break
if org_id is None:
print(f'Organization {org_name} not found')
return
# Get the inventory for the organization
inventory = make_request(f'{base_url}/organizations/{org_id}/inventory/devices')
if inventory is None:
return
# Write the inventory to a CSV file
with open(filename, 'w', newline='') as csvfile:
fieldnames = ['serial', 'model', 'networkId', 'mac', 'claimedAt']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
for device in inventory:
writer.writerow(device)
print(f'Inventory for organization "{org_name}" saved to {filename}')
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Get inventory for a Meraki organization')
parser.add_argument('-k', '--api_key', required=True, help='Meraki API key')
parser.add_argument('-o', '--org_name', required=True, help='Meraki organization name')
parser.add_argument('-f', '--filename', required=True, help='Output CSV file')
args = parser.parse_args()
get_inventory(args.api_key, args.org_name, args.filename)
Steps to Run the Updated Scripts
-
Ensure your conda environment is activated:
conda activate meraki_env -
Run the updated scripts with the appropriate arguments:
-
Get client count:
python scripts/clientcount.py -k $MERAKI_DASHBOARD_API_KEY -o "DeLab" -
Get license information:
python scripts/get_license.py -k $MERAKI_DASHBOARD_API_KEY -o "DeLab" -
Get inventory list:
python scripts/inventorycsv.py -k $MERAKI_DASHBOARD_API_KEY -o "DeLab" -f DeLab_inventory_list.csv
By adding the retry mechanism to these scripts, you can handle API rate limits more gracefully and ensure that your scripts can complete their tasks even when faced with temporary API restrictions. If you encounter any other issues or have further questions, please let me know!
The error message indicates that the API rate limit has been exceeded for your organization. This means that the Meraki API has received too many requests in a short period of time. To handle this, you can implement a retry mechanism with exponential backoff to wait before retrying the request.
Here is the updated clientcount.py script with a retry mechanism:
Updated clientcount.py with Retry Mechanism
import requests
import argparse
import time
import json
def get_client_count(api_key, org_name):
base_url = 'https://api.meraki.com/api/v1'
headers = {
'Authorization': f'Bearer {api_key}'
}
def make_request(url):
retries = 5
for i in range(retries):
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.json()
elif response.status_code == 429:
print(f"API rate limit exceeded. Retrying in {2 ** i} seconds...")
time.sleep(2 ** i)
else:
print(f"Error: {response.status_code} - {response.text}")
return None
return None
# Get the list of organizations
orgs = make_request(f'{base_url}/organizations')
if orgs is None:
return
# Find the organization ID for the given name
org_id = None
for org in orgs:
if org['name'] == org_name:
org_id = org['id']
break
if org_id is None:
print(f'Organization {org_name} not found')
return
# Get the list of networks in the organization
networks = make_request(f'{base_url}/organizations/{org_id}/networks')
if networks is None:
return
# Count the number of unique clients across all networks
unique_clients = set()
for network in networks:
network_id = network['id']
clients = make_request(f'{base_url}/networks/{network_id}/clients')
if clients is None:
continue
for client in clients:
unique_clients.add(client['mac'])
print(f'Total unique client MAC addresses across all WLAN APs: {len(unique_clients)}')
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Get client count for a Meraki organization')
parser.add_argument('-k', '--api_key', required=True, help='Meraki API key')
parser.add_argument('-o', '--org_name', required=True, help='Meraki organization name')
args = parser.parse_args()
get_client_count(args.api_key, args.org_name)
Explanation of Changes
- Retry Mechanism: The
make_requestfunction implements retries with exponential backoff for handling rate limit errors (HTTP 429). - Modularized API Requests: The
make_requestfunction is used to handle all API requests, ensuring consistent error handling and retry logic.
Steps to Run the Updated Script
-
Ensure your conda environment is activated:
conda activate meraki_env -
Run the updated script with the appropriate arguments:
python scripts/clientcount.py -k $MERAKI_DASHBOARD_API_KEY -o "DeLab"
This script should now handle API rate limits more gracefully by retrying failed requests with exponential backoff. If you continue to encounter issues, please provide the specific error message for further assistance.