Skip to content

Commit e7d3c0f

Browse files
author
Shiyue Cheng
committed
Updated with v1.0.0b3 release
1 parent 805ea72 commit e7d3c0f

20 files changed

Lines changed: 588 additions & 483 deletions

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,10 @@ While you can make direct HTTP requests to dashboard API in any programming lang
2828
* `pip install meraki`
2929
* If you have both Python3 and Python2 installed, you may need to use `pip3` (so `pip3 install meraki`) along with `python3` on your system
3030
* If _meraki_ was previously installed, you can upgrade to the latest stable (non-beta) release with `pip install --upgrade meraki`
31-
* You can specify the version of the library, for example `pip install meraki==0.110.0` for v0 or `pip install meraki==1.0.0b3` for v1 beta
32-
* To see the [release history](https://pypi.org/project/meraki/#history), you can also use `pip install meraki==` without including a version number
31+
32+
5. Meraki dashboard API v1 is currently in beta, so if you clone this repository and want to use v1 locally, rename the folder _meraki_v1_ to _meraki_, replacing the v0 contents there. You can also specify the version of the library when installing with _pip_:
33+
* For example, `pip install meraki==0.110.0` for v0 or `pip install meraki==1.0.0b3` for v1 beta
34+
* To see the full [release history](https://pypi.org/project/meraki/#history), you can also use `pip install meraki==` without including a version number
3335

3436
## Usage
3537
1. Export your API key as an [environment variable](https://www.twilio.com/blog/2017/01/how-to-set-environment-variables.html), for example:

meraki/aio/rest_session.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ def __init__(
9696
# Check base URL
9797
if 'v1' in self._base_url:
9898
sys.exit(f'If you want to use the Python library with v1 paths ({self._base_url} was configured as the base'
99-
f' URL), then install the v1 library. For example: pip install meraki==1.0.0b1')
99+
f' URL), then install the v1 library. See the "Setup" section @ https://github.com/meraki/dashboard-api-python/')
100100
elif self._base_url[-1] == '/':
101101
self._base_url = self._base_url[:-1]
102102

meraki_v1/__init__.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@
1717
from .config import (
1818
API_KEY_ENVIRONMENT_VARIABLE, DEFAULT_BASE_URL, SINGLE_REQUEST_TIMEOUT, CERTIFICATE_PATH, WAIT_ON_RATE_LIMIT,
1919
NGINX_429_RETRY_WAIT_TIME, ACTION_BATCH_RETRY_WAIT_TIME, RETRY_4XX_ERROR, RETRY_4XX_ERROR_WAIT_TIME,
20-
MAXIMUM_RETRIES, OUTPUT_LOG, LOG_PATH, LOG_FILE_PREFIX, PRINT_TO_CONSOLE, SUPPRESS_LOGGING, SIMULATE_API_CALLS
20+
MAXIMUM_RETRIES, OUTPUT_LOG, LOG_PATH, LOG_FILE_PREFIX, PRINT_TO_CONSOLE, SUPPRESS_LOGGING, SIMULATE_API_CALLS,
21+
BE_GEO_ID, MERAKI_PYTHON_SDK_CALLER
2122
)
2223

23-
__version__ = '1.0.0b1'
24+
__version__ = '1.0.0b3'
2425

2526
class DashboardAPI(object):
2627
"""
@@ -53,7 +54,7 @@ def __init__(self, api_key=None, base_url=DEFAULT_BASE_URL, single_request_timeo
5354
retry_4xx_error=RETRY_4XX_ERROR, retry_4xx_error_wait_time=RETRY_4XX_ERROR_WAIT_TIME,
5455
maximum_retries=MAXIMUM_RETRIES, output_log=OUTPUT_LOG, log_path=LOG_PATH,
5556
log_file_prefix=LOG_FILE_PREFIX, print_console=PRINT_TO_CONSOLE, suppress_logging=SUPPRESS_LOGGING,
56-
simulate=SIMULATE_API_CALLS, be_geo_id='', caller=''):
57+
simulate=SIMULATE_API_CALLS, be_geo_id=BE_GEO_ID, caller=MERAKI_PYTHON_SDK_CALLER):
5758
# Check API key
5859
api_key = api_key or os.environ.get(API_KEY_ENVIRONMENT_VARIABLE)
5960
if not api_key:

meraki_v1/aio/__init__.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,9 @@
1717
API_KEY_ENVIRONMENT_VARIABLE, DEFAULT_BASE_URL, SINGLE_REQUEST_TIMEOUT, CERTIFICATE_PATH, WAIT_ON_RATE_LIMIT,
1818
NGINX_429_RETRY_WAIT_TIME, ACTION_BATCH_RETRY_WAIT_TIME, RETRY_4XX_ERROR, RETRY_4XX_ERROR_WAIT_TIME,
1919
MAXIMUM_RETRIES, OUTPUT_LOG, LOG_PATH, LOG_FILE_PREFIX, PRINT_TO_CONSOLE, SUPPRESS_LOGGING, SIMULATE_API_CALLS,
20-
AIO_MAXIMUM_CONCURRENT_REQUESTS
20+
AIO_MAXIMUM_CONCURRENT_REQUESTS, BE_GEO_ID, MERAKI_PYTHON_SDK_CALLER
2121
)
2222

23-
__version__ = '1.0.0b1'
2423

2524
class AsyncDashboardAPI:
2625
"""
@@ -43,6 +42,8 @@ class AsyncDashboardAPI:
4342
- suppress_logging (boolean): disable all logging? you're on your own then!
4443
- simulate (boolean): simulate POST/PUT/DELETE calls to prevent changes?
4544
- maximum_concurrent_requests (integer): number of concurrent API requests for asynchronous class
45+
- be_geo_id (string): optional partner identifier for API usage tracking; can also be set as an environment variable BE_GEO_ID
46+
- caller (string): optional identifier for API usage tracking; can also be set as an environment variable MERAKI_PYTHON_SDK_CALLER
4647
"""
4748

4849
def __init__(self, api_key=None, base_url=DEFAULT_BASE_URL, single_request_timeout=SINGLE_REQUEST_TIMEOUT,
@@ -52,11 +53,18 @@ def __init__(self, api_key=None, base_url=DEFAULT_BASE_URL, single_request_timeo
5253
retry_4xx_error=RETRY_4XX_ERROR, retry_4xx_error_wait_time=RETRY_4XX_ERROR_WAIT_TIME,
5354
maximum_retries=MAXIMUM_RETRIES, output_log=OUTPUT_LOG, log_path=LOG_PATH,
5455
log_file_prefix=LOG_FILE_PREFIX, print_console=PRINT_TO_CONSOLE, suppress_logging=SUPPRESS_LOGGING,
55-
simulate=SIMULATE_API_CALLS, maximum_concurrent_requests=AIO_MAXIMUM_CONCURRENT_REQUESTS):
56+
simulate=SIMULATE_API_CALLS, maximum_concurrent_requests=AIO_MAXIMUM_CONCURRENT_REQUESTS,
57+
be_geo_id=BE_GEO_ID, caller=MERAKI_PYTHON_SDK_CALLER):
5658
# Check API key
5759
api_key = api_key or os.environ.get(API_KEY_ENVIRONMENT_VARIABLE)
5860
if not api_key:
5961
raise APIKeyError()
62+
63+
# Pull the BE GEO ID from an environment variable if present
64+
be_geo_id = be_geo_id or os.environ.get('BE_GEO_ID')
65+
66+
# Pull the caller from an environment variable if present
67+
caller = caller or os.environ.get('MERAKI_PYTHON_SDK_CALLER')
6068

6169
# Configure logging
6270
if not suppress_logging:
@@ -98,7 +106,9 @@ def __init__(self, api_key=None, base_url=DEFAULT_BASE_URL, single_request_timeo
98106
retry_4xx_error_wait_time=retry_4xx_error_wait_time,
99107
maximum_retries=maximum_retries,
100108
simulate=simulate,
101-
maximum_concurrent_requests=maximum_concurrent_requests
109+
maximum_concurrent_requests=maximum_concurrent_requests,
110+
be_geo_id=be_geo_id,
111+
caller=caller,
102112
)
103113

104114
# API endpoints by section

meraki_v1/aio/api/__init__.py

Whitespace-only changes.

meraki_v1/aio/api/appliance.py

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,22 @@ def __init__(self, session):
33
super().__init__()
44
self._session = session
55

6+
async def getDeviceApplianceDhcpSubnets(self, serial: str):
7+
"""
8+
**Return the DHCP subnet information for an appliance**
9+
https://developer.cisco.com/docs/meraki-api-v1/#!get-device-appliance-dhcp-subnets
10+
11+
- serial (string)
12+
"""
13+
14+
metadata = {
15+
'tags': ['appliance', 'monitor', 'dhcp', 'subnets'],
16+
'operation': 'getDeviceApplianceDhcpSubnets',
17+
}
18+
resource = f'/devices/{serial}/appliance/dhcp/subnets'
19+
20+
return await self._session.get(metadata, resource)
21+
622
async def getDeviceAppliancePerformance(self, serial: str):
723
"""
824
**Return the performance score for a single device. Only primary MX devices supported. If no data is available, a 204 error code is returned.**
@@ -1186,6 +1202,99 @@ async def updateNetworkApplianceVpnSiteToSiteVpn(self, networkId: str, mode: str
11861202

11871203
return await self._session.put(metadata, resource, payload)
11881204

1205+
async def getNetworkApplianceWarmSpare(self, networkId: str):
1206+
"""
1207+
**Return MX warm spare settings**
1208+
https://developer.cisco.com/docs/meraki-api-v1/#!get-network-appliance-warm-spare
1209+
1210+
- networkId (string)
1211+
"""
1212+
1213+
metadata = {
1214+
'tags': ['appliance', 'configure', 'warmSpare'],
1215+
'operation': 'getNetworkApplianceWarmSpare',
1216+
}
1217+
resource = f'/networks/{networkId}/appliance/warmSpare'
1218+
1219+
return await self._session.get(metadata, resource)
1220+
1221+
async def updateNetworkApplianceWarmSpare(self, networkId: str, enabled: bool, **kwargs):
1222+
"""
1223+
**Update MX warm spare settings**
1224+
https://developer.cisco.com/docs/meraki-api-v1/#!update-network-appliance-warm-spare
1225+
1226+
- networkId (string)
1227+
- enabled (boolean): Enable warm spare
1228+
- spareSerial (string): Serial number of the warm spare appliance
1229+
- uplinkMode (string): Uplink mode, either virtual or public
1230+
- virtualIp1 (string): The WAN 1 shared IP
1231+
- virtualIp2 (string): The WAN 2 shared IP
1232+
"""
1233+
1234+
kwargs.update(locals())
1235+
1236+
metadata = {
1237+
'tags': ['appliance', 'configure', 'warmSpare'],
1238+
'operation': 'updateNetworkApplianceWarmSpare',
1239+
}
1240+
resource = f'/networks/{networkId}/appliance/warmSpare'
1241+
1242+
body_params = ['enabled', 'spareSerial', 'uplinkMode', 'virtualIp1', 'virtualIp2']
1243+
payload = {k: v for (k, v) in kwargs.items() if k in body_params}
1244+
1245+
return await self._session.put(metadata, resource, payload)
1246+
1247+
async def swapNetworkApplianceWarmSpare(self, networkId: str):
1248+
"""
1249+
**Swap MX primary and warm spare appliances**
1250+
https://developer.cisco.com/docs/meraki-api-v1/#!swap-network-appliance-warm-spare
1251+
1252+
- networkId (string)
1253+
"""
1254+
1255+
metadata = {
1256+
'tags': ['appliance', 'configure', 'warmSpare'],
1257+
'operation': 'swapNetworkApplianceWarmSpare',
1258+
}
1259+
resource = f'/networks/{networkId}/appliance/warmSpare/swap'
1260+
1261+
return await self._session.post(metadata, resource)
1262+
1263+
async def getOrganizationApplianceSecurityEvents(self, organizationId: str, total_pages=1, direction='next', **kwargs):
1264+
"""
1265+
**List the security events for an organization**
1266+
https://developer.cisco.com/docs/meraki-api-v1/#!get-organization-appliance-security-events
1267+
1268+
- organizationId (string)
1269+
- total_pages (integer or string): total number of pages to retrieve, -1 or "all" for all pages
1270+
- direction (string): direction to paginate, either "next" (default) or "prev" page
1271+
- t0 (string): The beginning of the timespan for the data. The maximum lookback period is 365 days from today.
1272+
- t1 (string): The end of the timespan for the data. t1 can be a maximum of 365 days after t0.
1273+
- timespan (number): The timespan for which the information will be fetched. If specifying timespan, do not specify parameters t0 and t1. The value must be in seconds and be less than or equal to 365 days. The default is 31 days.
1274+
- perPage (integer): The number of entries per page returned. Acceptable range is 3 - 1000. Default is 100.
1275+
- startingAfter (string): A token used by the server to indicate the start of the page. Often this is a timestamp or an ID but it is not limited to those. This parameter should not be defined by client applications. The link for the first, last, prev, or next page in the HTTP Link header should define it.
1276+
- endingBefore (string): A token used by the server to indicate the end of the page. Often this is a timestamp or an ID but it is not limited to those. This parameter should not be defined by client applications. The link for the first, last, prev, or next page in the HTTP Link header should define it.
1277+
- sortOrder (string): Sorted order of security events based on event detection time. Order options are 'ascending' or 'descending'. Default is ascending order.
1278+
"""
1279+
1280+
kwargs.update(locals())
1281+
1282+
if 'sortOrder' in kwargs:
1283+
options = ['ascending', 'descending']
1284+
assert kwargs['sortOrder'] in options, f'''"sortOrder" cannot be "{kwargs['sortOrder']}", & must be set to one of: {options}'''
1285+
1286+
metadata = {
1287+
'tags': ['appliance', 'monitor', 'security', 'events'],
1288+
'operation': 'getOrganizationApplianceSecurityEvents',
1289+
}
1290+
resource = f'/organizations/{organizationId}/appliance/security/events'
1291+
1292+
query_params = ['t0', 't1', 'timespan', 'perPage', 'startingAfter', 'endingBefore', 'sortOrder']
1293+
params = {k: v for (k, v) in kwargs.items() if k in query_params}
1294+
1295+
return await self._session.get_pages(metadata, resource, params, total_pages, direction)
1296+
1297+
11891298
async def getOrganizationApplianceSecurityIntrusion(self, organizationId: str):
11901299
"""
11911300
**Returns all supported intrusion settings for an organization**
@@ -1224,3 +1333,80 @@ async def updateOrganizationApplianceSecurityIntrusion(self, organizationId: str
12241333

12251334
return await self._session.put(metadata, resource, payload)
12261335

1336+
async def getOrganizationApplianceThirdPartyVPNPeers(self, organizationId: str):
1337+
"""
1338+
**Return the third party VPN peers for an organization**
1339+
https://developer.cisco.com/docs/meraki-api-v1/#!get-organization-appliance-third-party-v-p-n-peers
1340+
1341+
- organizationId (string)
1342+
"""
1343+
1344+
metadata = {
1345+
'tags': ['appliance', 'configure', 'thirdPartyVPNPeers'],
1346+
'operation': 'getOrganizationApplianceThirdPartyVPNPeers',
1347+
}
1348+
resource = f'/organizations/{organizationId}/appliance/thirdPartyVPNPeers'
1349+
1350+
return await self._session.get(metadata, resource)
1351+
1352+
async def updateOrganizationApplianceThirdPartyVPNPeers(self, organizationId: str, peers: list):
1353+
"""
1354+
**Update the third party VPN peers for an organization**
1355+
https://developer.cisco.com/docs/meraki-api-v1/#!update-organization-appliance-third-party-v-p-n-peers
1356+
1357+
- organizationId (string)
1358+
- peers (array): The list of VPN peers
1359+
"""
1360+
1361+
kwargs = locals()
1362+
1363+
metadata = {
1364+
'tags': ['appliance', 'configure', 'thirdPartyVPNPeers'],
1365+
'operation': 'updateOrganizationApplianceThirdPartyVPNPeers',
1366+
}
1367+
resource = f'/organizations/{organizationId}/appliance/thirdPartyVPNPeers'
1368+
1369+
body_params = ['peers']
1370+
payload = {k: v for (k, v) in kwargs.items() if k in body_params}
1371+
1372+
return await self._session.put(metadata, resource, payload)
1373+
1374+
async def getOrganizationApplianceVpnVpnFirewallRules(self, organizationId: str):
1375+
"""
1376+
**Return the firewall rules for an organization's site-to-site VPN**
1377+
https://developer.cisco.com/docs/meraki-api-v1/#!get-organization-appliance-vpn-vpn-firewall-rules
1378+
1379+
- organizationId (string)
1380+
"""
1381+
1382+
metadata = {
1383+
'tags': ['appliance', 'configure', 'vpn', 'vpnFirewallRules'],
1384+
'operation': 'getOrganizationApplianceVpnVpnFirewallRules',
1385+
}
1386+
resource = f'/organizations/{organizationId}/appliance/vpn/vpnFirewallRules'
1387+
1388+
return await self._session.get(metadata, resource)
1389+
1390+
async def updateOrganizationApplianceVpnVpnFirewallRules(self, organizationId: str, **kwargs):
1391+
"""
1392+
**Update the firewall rules of an organization's site-to-site VPN**
1393+
https://developer.cisco.com/docs/meraki-api-v1/#!update-organization-appliance-vpn-vpn-firewall-rules
1394+
1395+
- organizationId (string)
1396+
- rules (array): An ordered array of the firewall rules (not including the default rule)
1397+
- syslogDefaultRule (boolean): Log the special default rule (boolean value - enable only if you've configured a syslog server) (optional)
1398+
"""
1399+
1400+
kwargs.update(locals())
1401+
1402+
metadata = {
1403+
'tags': ['appliance', 'configure', 'vpn', 'vpnFirewallRules'],
1404+
'operation': 'updateOrganizationApplianceVpnVpnFirewallRules',
1405+
}
1406+
resource = f'/organizations/{organizationId}/appliance/vpn/vpnFirewallRules'
1407+
1408+
body_params = ['rules', 'syslogDefaultRule']
1409+
payload = {k: v for (k, v) in kwargs.items() if k in body_params}
1410+
1411+
return await self._session.put(metadata, resource, payload)
1412+

0 commit comments

Comments
 (0)