HOWTO: Push an update to devices for a specific app which isn't the most up to date version

PaulF
Meraki Employee All-Star Meraki Employee All-Star
Meraki Employee All-Star

HOWTO: Push an update to devices for a specific app which isn't the most up to date version

Morning all.

 

So, at a conference where we needed to push an update to an app immediately because of bugs, etc.

 

Whilst you can go into a device's info page and push, and also do this from other pages, we wanted to ensure that we only did this for devices where the app version DIDN'T match a particular version, to avoid disruption to other devices

 

You'll need the following libraries installed:

  • Meraki
  • logging, sys, getopt, csv
  • pandas
  • json 

 

You'll call it with:

 

python3 PushAppByAppIDReadFromCSV.py -k <YOURAPIKEY> -n <YOURMERAKINETWORKID>

 

It requires a download of the CSV for the app in Question. This is from Systems Manager > Software. Click on the required app, then Export to CSV :

 

It requires this to be called : 

devices_with_software.csv

Screenshot 2025-08-03 at 08.15.05.png

It also requires your network ID: Go to Systems Manager > General and scroll all the way to the bottom of the page

 

Lastly, it requires the SM app ID: Go to Systems Manager > Apps and click on the required app. In the URL will be the SM app ID

 

We use PANDAS for three reasons:

  1. It's really good for importing multi columned CSVs
  2. It's fast!
  3. It's really easy to import a list of dictionaries and working with it, which is what the response is from the GetNetworkSMDevices API call

 

 

import meraki
import logging, sys, getopt, csv
import pandas as pd
import json

def main(argv):

    # static args:
    # Most recent version number of the app
    search_value = '5.0.0'

    # app ID in SM
    app_ids = ['57814960XXXXXXXXXXXXXXXXXXX']
    
    # init vars
    arg_apikey = ''
    arg_network_id = ''

    # read ARGs
    try:
        opts, args = getopt.getopt(argv, 'k:n:')
    except getopt.GetOptError:
        printhelp(argv)
        sys.exit(2)

    for opt, arg in opts:
        if opt == '-k':
            arg_apikey = arg
        elif opt == '-n':
            arg_network_id = arg

    if arg_apikey == '' or arg_network_id == '':
        printhelp(argv)
        sys.exit(2)

    # Read the CSV
    df = pd.read_csv('devices_with_software.csv')
    # Filter rows where 'column_name' equals the search_value
    # and create a new data frame
    filtered_df = df[df['version'] != search_value]

    client = meraki.DashboardAPI(api_key=arg_apikey)

    # get all devices in the sm network
    deviceList = client.sm.getNetworkSmDevices(networkId=arg_network_id)
    # MUCH easier to work with DICTs in a LIST in Pandas, so let's import the 
    deviceListDF = pd.DataFrame(deviceList)

    # iterate through filtered_df to get serial number
    for index, row in filtered_df.iterrows():
        serialNumber = row["serialNumber"]
        # now search through deviceListDF and get SM device ID

        try:
            # we'll have a try, just in case the device weirdly doesn't exist
            deviceIDList = deviceListDF.loc[deviceListDF['serialNumber'] == serialNumber, 'id'].values
            deviceID = str(deviceIDList[0])
            print("Device ID: ", deviceID, " serial number: ", serialNumber)

            try:
                response = client.sm.installNetworkSmDeviceApps(
                    arg_network_id, deviceID, app_ids,
                    force=True
                )
            except meraki.APIError as e:
                print(e.message)
                sys.exit(2)
        except Exception as e:
            print(e)


def printhelp():
    # prints help information
    print('This is a script that updates a given app where the app is not the most recent version.')
    print("You'll need to export the CSV from:")
    print("* Systems Manager > Software")
    print("* Click on the app in question")
    print("* Export to CSV on the right")
    print(" ")
    print(" It needs:")
    print("serial, name,,NetworkName")
    print('')
    print('Mandatory arguments:')
    print(' -k <api key>        : Your Meraki Dashboard API key')
    print(' -n number           : Your Meraki Network ID ')


if __name__ == '__main__':
    main(sys.argv[1:])

 

Good luck!

 

1 Reply 1
PhilipDAth
Kind of a big deal
Kind of a big deal

Thanks for sharing!

Get notified when there are additional replies to this discussion.