The “API first” approach of Mist Systems is undoubtedly one of the main reasons to become an attractive solution for large enterprises. It has simplified and enabled automation of wireless networks by providing REST APIs for almost every configuration and monitoring task that can be performed on a WLAN. In this post, I will be providing details on a Python script that can upgrade all the sites of your Organization with minimal downtime. The assumption is you have python already installed and have some basic knowledge on the language. The libraries we are going to use in the script are “requests” and “json”. While json module is included in python, you may have to install requests module.
The API to upgrade the devices at a site is shown below
POST /api/v1/sites/:site_id/devices/upgrade
The API call requires payload in the following JSON format to perform the action.
{
"version": "3.1.5",
"enable_p2p": false,
// filters that can be used, if no filter specified, it means entire site
"device_ids": [
"00000000-0000-0000-1000-5c5b35584a6f"
]
"models": [
"AP41"
]
}
Version is the OS version you would like to upgrade to and enable_p2p allows you to upgrade only few devices at a time. Setting it to True will result in only up to 3 or 4 devices upgrading and rebooting simultaneously at each site while other APs continue to serve the clients. This will minimize downtime. But if the preference is to upgrade all of them at the same time during a change window, this has to be set to False. The device_ids and models are only filters that can be used if required. If no filters are specified, all the devices at the site will be upgraded.
As observed, to make the API call, the site_id variable has to be provided. Mist also provides an API to get list of sites in an Organization.
GET /api/v1/orgs/:org_id/sites
So, in the script we are going to be build, we need to first get a list of site IDs and use them to upgrade sites with json payload containing version and other variables.
To accomplish this, we define two functions that will perform each task.
The first function is to get the list of site IDs.
def getSiteDict(orgId):
sitesUrl = "https://api.mist.com/api/v1/orgs/" + orgId + "/sites" #API to get list of sites in your Ogranization
getSiteIds = requests.request("GET", sitesUrl , headers=headers) #API call performed
getSiteIds_json = getSiteIds.json() #Decodes the JSON data from API Request into a list
siteDict={}
for site in getSiteIds_json: #Loops through the list and appends site names and site IDs to the siteDict
try:
siteDict.update({site['name']:site['id']})
except Exception as e:
print(e)
return siteDict
We need to pass the OrgID as an argument to this function. This will enable the function to be reused if you are managing multiple organizations. The function will return a dictionary with <siteName, siteId> as key value pairs. Next we define a function to send the upgrade devices API call to each site. This function takes siteID as an argument.
def siteUpgrade(siteId):
payload = {
"version": "0.5.17360", #Version to upgrade to
"enable_p2p": True #Enabling peer to peer upgrade
}
payload=json.dumps(payload) #Converts the payload to JSON format
upgradeUrl = "https://api.mist.com/api/v1/sites/" + siteId + "/devices/upgrade" #API URL To upgrade the devices
upgradeCall = requests.request("POST", upgradeUrl , data=payload, headers=headers) #API call performed with the payload
return upgradeCall.status_code #Returns the HTTP Response code for the API call.
Now that we have the functions defined all we have to do is complete the puzzle to make function calls and perform the tasks. To do this we need OrgID and header which contains Token. The token needs to have read write privileges to perform the operations in this script.
orgId= "#Enter Org ID Here"
headers = {
'Authorization': "Token #here", # Token with read write acccess required
'Content-Type': "application/json",
}
siteDict=getSiteDict(orgId) #Function call to get siteDict
for siteName,siteId in siteDict.items(): #Loops through the Dictionary to make API calls for each site.
try:
upgradeStatus=siteUpgrade(siteId)
if upgradeStatus == 200: #HTTP Response is 200 for successful API calls.
print("Upgrade Successful for site " , siteName)
else:
print("Error Occurred ", upgradeStatus)
except Exception as e:
print(e)
The full script can be found below.
import requests, json
headers = {
'Authorization': "Token #here", # Token with read write access required
'Content-Type': "application/json",
}
def getSiteDict(orgId):
sitesUrl = "https://api.mist.com/api/v1/orgs/" + orgId + "/sites" #API to get list of sites in your Organization
getSiteIds = requests.request("GET", sitesUrl , headers=headers) #API call performed
getSiteIds_json = getSiteIds.json() #Decodes the JSON data from API Request into a list
siteDict={}
for site in getSiteIds_json: #Loops through the list and appends site names and site IDs to the siteDict
try:
siteDict.update({site['name']:site['id']})
except Exception as e:
print(e)
return siteDict
def siteUpgrade(siteId):
payload = {
"version": "0.5.17360", #Version to upgrade to
"enable_p2p": True #Enabling peer to peer upgrade
}
payload=json.dumps(payload) #Converts the payload to JSON format
upgradeUrl = "https://api.mist.com/api/v1/sites/" + siteId + "/devices/upgrade" #API URL To upgrade the devices
upgradeCall = requests.request("POST", upgradeUrl , data=payload, headers=headers) #API call performed with the payload
return upgradeCall.status_code #Returns the HTTP Response code for the API call.
orgId= "#Enter Org ID Here"
siteDict=getSiteDict(orgId) #Function call to get siteDict
for siteName,siteId in siteDict.items(): #Loops through the Dictionary to make API calls for each site.
try:
upgradeStatus=siteUpgrade(siteId)
if upgradeStatus == 200: #HTTP Response is 200 for successful API calls.
print("Upgrade API call Successful for site " , siteName)
else:
print("Error Occurred ", upgradeStatus)
except Exception as e:
print(e)