Update work/tbx/meraki/sandbox_api.md

This commit is contained in:
2024-06-01 05:37:21 +00:00
parent 0b29344ea8
commit 280afc79a1

View File

@@ -274,4 +274,266 @@ source setup_env.sh
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!
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
```python
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
```python
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
1. **Ensure your conda environment is activated:**
```sh
conda activate meraki_env
```
2. **Run the updated scripts with the appropriate arguments:**
- **Get client count:**
```sh
python scripts/clientcount.py -k $MERAKI_DASHBOARD_API_KEY -o "DeLab"
```
- **Get license information:**
```sh
python scripts/get_license.py -k $MERAKI_DASHBOARD_API_KEY -o "DeLab"
```
- **Get inventory list:**
```sh
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
```python
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_request` function implements retries with exponential backoff for handling rate limit errors (HTTP 429).
- **Modularized API Requests**: The `make_request` function is used to handle all API requests, ensuring consistent error handling and retry logic.
### Steps to Run the Updated Script
1. **Ensure your conda environment is activated:**
```sh
conda activate meraki_env
```
2. **Run the updated script with the appropriate arguments:**
```sh
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.