<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Get Request for Multiple Sites in Network Platform API</title>
    <link>https://community.cisco.com/t5/network-platform-api/get-request-for-multiple-sites/m-p/5444938#M7003</link>
    <description>&lt;P&gt;Yeah that's it. Need to pull the DHCP reservations (Fixed IP address assignment as Meraki call it) across all the networks in the org.&lt;/P&gt;&lt;P&gt;Customer has 50+ sites, and wants a report for all sites. &lt;/P&gt;&lt;P&gt;I can do it for 1 site no dramas, but pulling it for the whole org is proving a bit more difficult. Keen to hear how it can be done. &lt;/P&gt;&lt;P&gt;I suppose the concept is the same for any setting across multiple Networks. &lt;/P&gt;</description>
    <pubDate>Tue, 27 Aug 2024 10:27:00 GMT</pubDate>
    <dc:creator>PeteWhit</dc:creator>
    <dc:date>2024-08-27T10:27:00Z</dc:date>
    <item>
      <title>Get Request for Multiple Sites</title>
      <link>https://community.cisco.com/t5/network-platform-api/get-request-for-multiple-sites/m-p/5444936#M7001</link>
      <description>&lt;P&gt;Hi team, hoping someone can help me out here.&lt;/P&gt;&lt;P&gt;I have a customer that wants a report of all their Fixed IP Assignments in each MX across their fleet.&lt;/P&gt;&lt;P&gt;There are over 100 MXs, all with fixed IPs in the DHCP scope.&lt;/P&gt;&lt;P&gt;When using postman, I can get the info from an individual network and Vlan using the getNetworkApplianceVlan command.&lt;/P&gt;&lt;P&gt;However, this isn't really scalable as you can imagine.&lt;/P&gt;&lt;P&gt;I'm hoping to be able to pull the fixed IP assignement setting for all 100 MXs inside the same org.  Any idea's how I can expan the getNetworkApplianceVlan command to scrape all networks and vlans, not just one? &lt;/P&gt;</description>
      <pubDate>Tue, 27 Aug 2024 01:26:48 GMT</pubDate>
      <guid>https://community.cisco.com/t5/network-platform-api/get-request-for-multiple-sites/m-p/5444936#M7001</guid>
      <dc:creator>PeteWhit</dc:creator>
      <dc:date>2024-08-27T01:26:48Z</dc:date>
    </item>
    <item>
      <title>Re: Get Request for Multiple Sites</title>
      <link>https://community.cisco.com/t5/network-platform-api/get-request-for-multiple-sites/m-p/5444937#M7002</link>
      <description>&lt;P&gt;To clarify, you want to know all the DHCP host reservations?&lt;/P&gt;</description>
      <pubDate>Tue, 27 Aug 2024 09:40:17 GMT</pubDate>
      <guid>https://community.cisco.com/t5/network-platform-api/get-request-for-multiple-sites/m-p/5444937#M7002</guid>
      <dc:creator>Philip D'Ath</dc:creator>
      <dc:date>2024-08-27T09:40:17Z</dc:date>
    </item>
    <item>
      <title>Re: Get Request for Multiple Sites</title>
      <link>https://community.cisco.com/t5/network-platform-api/get-request-for-multiple-sites/m-p/5444938#M7003</link>
      <description>&lt;P&gt;Yeah that's it. Need to pull the DHCP reservations (Fixed IP address assignment as Meraki call it) across all the networks in the org.&lt;/P&gt;&lt;P&gt;Customer has 50+ sites, and wants a report for all sites. &lt;/P&gt;&lt;P&gt;I can do it for 1 site no dramas, but pulling it for the whole org is proving a bit more difficult. Keen to hear how it can be done. &lt;/P&gt;&lt;P&gt;I suppose the concept is the same for any setting across multiple Networks. &lt;/P&gt;</description>
      <pubDate>Tue, 27 Aug 2024 10:27:00 GMT</pubDate>
      <guid>https://community.cisco.com/t5/network-platform-api/get-request-for-multiple-sites/m-p/5444938#M7003</guid>
      <dc:creator>PeteWhit</dc:creator>
      <dc:date>2024-08-27T10:27:00Z</dc:date>
    </item>
    <item>
      <title>Re: Get Request for Multiple Sites</title>
      <link>https://community.cisco.com/t5/network-platform-api/get-request-for-multiple-sites/m-p/5444939#M7004</link>
      <description>&lt;P&gt;This is where you are probably better off using Python/whatever to create a script to do it. ..&lt;/P&gt;&lt;P&gt;get list of networks in org&lt;/P&gt;&lt;P&gt;for each network&lt;/P&gt;&lt;P&gt;    get mx data&lt;/P&gt;&lt;P&gt;You'll probably get other requests over time that would require this sort of approach to perform efficiently, may as well start now &lt;SPAN class="lia-unicode-emoji" title=":grinning_face:"&gt;&lt;span class="lia-unicode-emoji" title=":grinning_face:"&gt;😀&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;</description>
      <pubDate>Tue, 27 Aug 2024 11:01:29 GMT</pubDate>
      <guid>https://community.cisco.com/t5/network-platform-api/get-request-for-multiple-sites/m-p/5444939#M7004</guid>
      <dc:creator>sungod</dc:creator>
      <dc:date>2024-08-27T11:01:29Z</dc:date>
    </item>
    <item>
      <title>Re: Get Request for Multiple Sites</title>
      <link>https://community.cisco.com/t5/network-platform-api/get-request-for-multiple-sites/m-p/5444940#M7005</link>
      <description>&lt;P&gt;A personal favorite of mine for a quick no-code solution is the &lt;A href="https://developer.cisco.com/docs/meraki-tools-google-sheets-add-on/" target="_blank" rel="noopener nofollow noreferrer"&gt;Meraki Tools for Google Sheets&lt;/A&gt; integration. You can use the Looper feature in it to select all networks to get a nice report pretty easily.&lt;/P&gt;</description>
      <pubDate>Tue, 27 Aug 2024 21:30:39 GMT</pubDate>
      <guid>https://community.cisco.com/t5/network-platform-api/get-request-for-multiple-sites/m-p/5444940#M7005</guid>
      <dc:creator>JasonMo</dc:creator>
      <dc:date>2024-08-27T21:30:39Z</dc:date>
    </item>
    <item>
      <title>Re: Get Request for Multiple Sites</title>
      <link>https://community.cisco.com/t5/network-platform-api/get-request-for-multiple-sites/m-p/5444941#M7006</link>
      <description>&lt;P&gt;Thanks for that, the Google sheet is a great tool.  It's so close to giving me what I need.  However, It still only does 1 Network and 1 Vlan at a time when requesting Vlan info. So I'd have to click into each network and Vlan to extra the data.&lt;/P&gt;&lt;P&gt;Meraki Reports &amp;gt; Group = Appliance &amp;gt; Reports = Network Appliance Vlan.  But I have to select a Network and a Vlan.  It gives me the data I want, but still on an individual level.&lt;/P&gt;&lt;P&gt;Ideally it needs to be all MXs and all Vlans.... give me the output. Might have to finally learn some python. &lt;/P&gt;</description>
      <pubDate>Wed, 28 Aug 2024 00:13:57 GMT</pubDate>
      <guid>https://community.cisco.com/t5/network-platform-api/get-request-for-multiple-sites/m-p/5444941#M7006</guid>
      <dc:creator>PeteWhit</dc:creator>
      <dc:date>2024-08-28T00:13:57Z</dc:date>
    </item>
    <item>
      <title>Re: Get Request for Multiple Sites</title>
      <link>https://community.cisco.com/t5/network-platform-api/get-request-for-multiple-sites/m-p/5444942#M7007</link>
      <description>&lt;P&gt;Hi &lt;A href="https://community.meraki.com/t5/user/viewprofilepage/user-id/100309"&gt;@PeteWhit&lt;/A&gt;,&lt;BR /&gt;&lt;BR /&gt;A script would definitely be the way to go with Meraki API. You can use the following logic as SunGod suggested -&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;&lt;P&gt;1. Get a list of networks - &lt;A href="https://developer.cisco.com/meraki/api-v1/get-organization-networks/" target="_blank" rel="noopener nofollow noreferrer"&gt;Get Organization Networks - Meraki Dashboard API v1 - Cisco Meraki Developer Hub&lt;/A&gt;&lt;BR /&gt;2. FOR Loop through the Networks&lt;/P&gt;&lt;P&gt;3. Use the NetworkID - and run &lt;A href="https://developer.cisco.com/meraki/api-v1/get-network-appliance-vlans/" target="_blank" rel="noopener nofollow noreferrer"&gt;Get Network Appliance Vlans - Meraki Dashboard API v1 - Cisco Meraki Developer Hub&lt;/A&gt; for every network&lt;/P&gt;&lt;P&gt;4. Look for "&lt;SPAN&gt;fixedIpAssignments" and that should be the data you are looking for.&lt;BR /&gt;&lt;BR /&gt;You can use the Code Snippet section in each relevant API call to understand the code equivalent which simplifies the job a lot!&lt;BR /&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/P&gt;</description>
      <pubDate>Wed, 28 Aug 2024 02:35:21 GMT</pubDate>
      <guid>https://community.cisco.com/t5/network-platform-api/get-request-for-multiple-sites/m-p/5444942#M7007</guid>
      <dc:creator>Craig.Peris</dc:creator>
      <dc:date>2024-08-28T02:35:21Z</dc:date>
    </item>
    <item>
      <title>Re: Get Request for Multiple Sites</title>
      <link>https://community.cisco.com/t5/network-platform-api/get-request-for-multiple-sites/m-p/5444943#M7008</link>
      <description>&lt;P&gt;There is an endpoint, &lt;EM&gt;Network Appliance Vlans&lt;/EM&gt;, that covers all VLANs for an MX network. Additionally, there is a "Looper" feature that will allow you to select multiple networks, all networks, or even multiple organizations.&lt;/P&gt;&lt;P&gt;&lt;SPAN class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-08-29 at 10.19.42 AM.png" style="width: 999px;"&gt;&lt;span class="lia-inline-image-display-wrapper" image-alt="image.png"&gt;&lt;img src="https://community.cisco.com/t5/image/serverpage/image-id/264025iD9AB8A8FD234A5B0/image-size/large?v=v2&amp;amp;px=999" role="button" title="image.png" alt="image.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;Hope this helps!&lt;/P&gt;</description>
      <pubDate>Thu, 29 Aug 2024 17:27:43 GMT</pubDate>
      <guid>https://community.cisco.com/t5/network-platform-api/get-request-for-multiple-sites/m-p/5444943#M7008</guid>
      <dc:creator>JasonMo</dc:creator>
      <dc:date>2024-08-29T17:27:43Z</dc:date>
    </item>
    <item>
      <title>Re: Get Request for Multiple Sites</title>
      <link>https://community.cisco.com/t5/network-platform-api/get-request-for-multiple-sites/m-p/5444944#M7009</link>
      <description>&lt;P&gt;Thanks &lt;A href="https://community.meraki.com/t5/user/viewprofilepage/user-id/194"&gt;@JasonMo&lt;/A&gt; - that's what I was after.  It spits out the raw data, but it was good enough to get me the info I needed.  Thanks for the assist.  Works well for those of us who aren't great with scripting.  &lt;/P&gt;</description>
      <pubDate>Fri, 30 Aug 2024 01:37:21 GMT</pubDate>
      <guid>https://community.cisco.com/t5/network-platform-api/get-request-for-multiple-sites/m-p/5444944#M7009</guid>
      <dc:creator>PeteWhit</dc:creator>
      <dc:date>2024-08-30T01:37:21Z</dc:date>
    </item>
    <item>
      <title>Re: Get Request for Multiple Sites</title>
      <link>https://community.cisco.com/t5/network-platform-api/get-request-for-multiple-sites/m-p/5444945#M7010</link>
      <description>&lt;P&gt;Below is what I came up with a while ago. It will output an excel file with all the DHCP reservations for all networks for all orgs that the API key can access.&lt;BR /&gt;&lt;BR /&gt;Note API Key is retrieved from an Environment variable.&lt;/P&gt;&lt;PRE class="lia-code-sample language-python"&gt;&lt;CODE&gt;import csv
from datetime import datetime
import os
import time
import meraki
import pandas as pd
import json
import xlsxwriter
import openpyxl
from collections import OrderedDict
import time

# This script get a list of all VLANs for All Meraki Networks in All Meraki Orgs the API Key has access to
#This also grab single subnet networks and skip any networks that has a passthrough appliances as they do not have a subnet.

#It then get all the DHCP reservations from each VLANs.

# Meraki API Key name. Allows to switch between different keys
MERAKI_DASHBOARD_API_KEY_NAME = 'MERAKI_API_KEY GOES HERE'  # Readonly key

#Set CSV / XLXS folder path
output_path = f"{os.path.dirname(__file__)}/output"

def main():
    if MERAKI_DASHBOARD_API_KEY_NAME in os.environ:
        print(f"API Key Environment variable [{MERAKI_DASHBOARD_API_KEY_NAME}] found.")

    else:
        print(f"API Key Environment variable [{MERAKI_DASHBOARD_API_KEY_NAME}] Does not exists!")
        exit(1)

    MERAKI_DASHBOARD_API_KEY = os.getenv(MERAKI_DASHBOARD_API_KEY_NAME)  # Get the actual Meraki API Key

    # Start a Meraki dashboard API session
    try:
        print(f"\nTrying to connect to Meraki API Using [{MERAKI_DASHBOARD_API_KEY_NAME}]")

        dashboard = meraki.DashboardAPI(
            api_key=MERAKI_DASHBOARD_API_KEY,
            base_url='https://api.meraki.com/api/v1/',
            print_console=False, output_log=False, suppress_logging=True,
            wait_on_rate_limit=True,
            maximum_retries=100
        )

    except meraki.APIError as e:
        print("Unable to connect to Meraki API.")
        print(f'Meraki API error: {e}')
        print(f'status code = {e.status}')
        print(f'reason = {e.reason}')
        print(f'error = {e.message}')

    else:

        # Get list of organizations to which the supplied API key has access to.
        organizations = dashboard.organizations.getOrganizations()
        organizations = sorted(organizations, key=lambda x: x['name'])  # Sort Org by name

        # Print name of the Orgs found
        print(f"Found: [{len(organizations)}] organisations.")
        for org in organizations:
            print(f"{org['name']}")

        all_orgs_networks_vlans = list() #Store a list of all the org vlans
        all_orgs_networks_vlans_dhcp_reservations = list()  # Store a list of all the org vlans reservations

        # Iterate through list of Orgs and gather clients details of all VLAN for each networks where there is an MX
        for org in organizations:

            all_org_networks = []  # Store all the networks in all orgs so we can write to a file later.

            print(f"\nAnalysing organization {org['name']}:")
            org_id = org['id']  # Save ID name for use later
            org_name = org['name']  # Save Org name for use later

            # Get list of networks in current organization
            try:
                org_networks = dashboard.organizations.getOrganizationNetworks(org_id)

            except meraki.APIError as e:

                print(f'Meraki API error: {e}')
                print(f'status code = {e.status}')
                print(f'reason = {e.reason}')
                print(f'error = {e.message}')
                continue

            except Exception as e:
                print(f'some other error: {e}')
                continue  # Skip error in current Mersaki network

            # Sort List of network by name
            org_networks = sorted(org_networks, key=lambda x: x['name'])

            # Iterate through networks in current organisation
            total = len(org_networks)  # count number of Meraki networks in this org
            counter = 1  # Keep count of number of network as we iterate through them.

            print(f'Iterating through {total} networks in organization in {org["name"]} to get list of VLAN information')

            # Create a new list networks
            current_org_networks_info = []

            # Loop through the list of networks and retrieve the VLAN info
            for network in org_networks:

                print(f'Processing [{org["name"]}] Network: {network["name"]}')

                #We can check if a network has vlans by using below endpoint
                # https://developer.cisco.com/meraki/api/get-network-appliance-vlans-settings/
                #
                #However to reduce the number of API calls. This will be skipped

                # Create a new dictionary to store the network info
                network_info = {}

                # Add the required fields to the new dictionary
                network_info["id"] = network["id"]
                network_info["organizationId"] = network["organizationId"]
                network_info["name"] = network["name"]
                network_info["productTypes"] = network["productTypes"]
                network_info["timeZone"] = network["timeZone"]
                network_info["tags"] = network["tags"]
                network_info["isBoundToConfigTemplate"] = network["isBoundToConfigTemplate"]
                network_info["url"] = network["url"]

                network_vlans = list() #Use to hold all the vlan or empty if no vlans

                vlan_details = {} #Store the vlan details for each vlan


                #If product type has "appliance" then it will have a vlan subnet for us to grab
                if 'appliance' in network['productTypes']:

                    #Get VLAN Info
                    try:
                        vlans = dashboard.appliance.getNetworkApplianceVlans(network["id"])

                        #vlans now has the VLAN details including any DHCP reservations
                        #Now loop through all the VLAn and get the DHCP Reservations clients MAC &amp;amp; IP
                        for vlan in vlans:

                            fixedIpAssignments = vlan['fixedIpAssignments']

                            for key in fixedIpAssignments:
                                # vlan_details['organizationId'] = network['organizationId']
                                # vlan_details['net_name'] = network['name']
                                # vlan_details["vlan_name"] = vlan['name']
                                # vlan_details['dnsNameservers'] = vlan['dnsNameservers']

                                # vlan_details['reservation_name'] = fixedIpAssignments[f"{key}"]['name']
                                # vlan_details['reservation_mac'] = f"{key}"
                                vlan_details['reservation_ip'] = fixedIpAssignments[f"{key}"]['ip']

                                all_orgs_networks_vlans_dhcp_reservations.append(
                                                                                 {'organizationId': network['organizationId'],
                                                                                  'net_name': network['name'],
                                                                                  'vlan_name': vlan['name'],
                                                                                 'dnsNameservers': vlan['dnsNameservers'],
                                                                                  'reservation_name': fixedIpAssignments[f"{key}"]['name'],
                                                                                  'reservation_mac': f"{key}",
                                                                                  'reservation_ip': fixedIpAssignments[f"{key}"]['ip']
                                                                                  }
                                                                                 )

                    except meraki.APIError as e:

                        if e.status == 400: #Vlan not enable for this network as only a single subnet

                            #Get the single VLAN subnet and assume VLAN ID of '1'

                            #print(f'Error Network: {network["name"]}: {e.message}')

                            #Check and skip any network &amp;amp; appliances in passthrough mode.
                            #They won't have any subnet to retrieve

                            # if 'ACM-VNET-MEL-APAS-ACM-01' in network['name']:
                            #     print('Pass through mode network')

                            #Get the single VLAN
                            try:
                                single_vlan_info = dashboard.appliance.getNetworkApplianceSingleLan(network["id"])

                                fixedIpAssignments = single_vlan_info['fixedIpAssignments']

                                for key in fixedIpAssignments:

                                    vlan_details['reservation_ip'] = fixedIpAssignments[f"{key}"]['ip']

                                    all_orgs_networks_vlans_dhcp_reservations.append(
                                        {'organizationId': network['organizationId'],
                                         'net_name': network['name'],
                                         'vlan_name': 'Default',
                                         'dnsNameservers': single_vlan_info['dnsCustomNameservers'],
                                         'reservation_name': fixedIpAssignments[f"{key}"]['name'],
                                         'reservation_mac': f"{key}",
                                         'reservation_ip': fixedIpAssignments[f"{key}"]['ip']
                                         }
                                    )
                                    # print(f"Done")


                            except meraki.APIError as e2:

                                if e2.status == 400:
                                    print(f"Network in Passthrough mode or some other error. Skipping!")
                                    #'Single LAN is not available for networks in passthrough mode'
                                    continue
                                else:
                                    print(f'Some other error for network without VLANs.')
                                    continue

                            #If we are here then there is a single subnet to grab
                            vlan_subnet = {1, single_vlan_info['subnet']}
                            print(f"VLAN [1]: - Subnet [{single_vlan_info['subnet']}]")
                            network_vlans.append(vlan_subnet)

                            # Also store the VLAN in the All Org VLAN list for later usage
                            all_orgs_networks_vlans.append({'net_name': network["name"], 'net_id': network["id"],
                                                            'vlan_id': 1, 'vlan_subnet': single_vlan_info['subnet']})
                            continue

                        elif e.status == 429:
                            #We have hit the rate limit. Back off by sleeping for a bit
                            print(f'Error Network: {network["name"]}: {e.message}. Sleeping for 5 seconds.')
                            #time.sleep(int(response.headers["Retry-After"]))
                            time.sleep(5)  # Sleep for 5 seconds
                            continue

                        else:
                            print(f'Error Network: {network["name"]}')
                            print(f'Meraki API error: {e}')
                            print(f'status code = {e.status}')
                            print(f'reason = {e.reason}')
                            print(f'error = {e.message}')
                            continue

                    #If we are here then there are some vlan subnets to process
                    # Loop through the appliance vlan info and get all VLANs subnets
                    for vlan in vlans:
                        # print(f"VLAN ID: [{$vlan['id']}] Subnet: {$vlan['subnet']} ")
                        vlan_subnet = {vlan['id'], vlan['subnet']}
                        print(f"VLAN [{vlan['id']}]: - Subnet [{vlan['subnet']}]")
                        network_vlans.append(vlan_subnet)

                        #Also store the VLAN in the All Org VLAN list for later usage
                        all_orgs_networks_vlans.append({'net_name': network["name"], 'net_id': network["id"],
                                              'vlan_id': vlan['id'], 'vlan_subnet': vlan['subnet']})

                #store the network vlans (or empty if not an appliance network
                network_info['vlans'] = network_vlans

                # Add the new dictionary to the list
                current_org_networks_info.append(network_info)

            print(f"Network info gathering for [{org['name'] }] completed.")

            #Combine the curen org network info into the all_org dict for later use
            all_org_networks = current_org_networks_info + all_org_networks

        #Sort the networks by name
        #all_orgs_networks_vlans
        df_all_orgs_networks_vlans = pd.DataFrame(all_orgs_networks_vlans)
        df_all_orgs_networks_vlans_dhcp_reservations = pd.DataFrame(all_orgs_networks_vlans_dhcp_reservations)


        #df_all_org_networks_info = pd.DataFrame(all_org_networks)
        #
        # write the DataFrame to a CSV file
        current_datetime = datetime.now().strftime("%Y-%m-%d %H-%M-%S")
        filename = f"{output_path}/all-orgs_networks-vlan-info--{current_datetime}.xlsx"

        #df_all_org_networks_info.to_excel(filename)
        df_all_orgs_networks_vlans.to_excel(filename)
        print(f"Exported[VLANS to file] filename: {filename}")


        #Write DHCP reservation to file
        current_datetime = datetime.now().strftime("%Y-%m-%d %H-%M-%S")
        filename = f"{output_path}/all-orgs_networks-dhcp-reservation-info--{current_datetime}.xlsx"

        #df_all_org_networks_info.to_excel(filename)
        df_all_orgs_networks_vlans_dhcp_reservations.to_excel(filename)
        print(f"Exported [DHCP reservation to file] filename: {filename}")

if __name__ == "__main__":
    # Call Main to do all the actual work.
    start_time = datetime.now()
    main()
    end_time = datetime.now()
    print(f'\nScript complete, total runtime {end_time - start_time}')&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Fri, 06 Sep 2024 06:02:59 GMT</pubDate>
      <guid>https://community.cisco.com/t5/network-platform-api/get-request-for-multiple-sites/m-p/5444945#M7010</guid>
      <dc:creator>amabt</dc:creator>
      <dc:date>2024-09-06T06:02:59Z</dc:date>
    </item>
  </channel>
</rss>

