Python List Variables

SOLVED
KRobert
Head in the Cloud

Python List Variables

I am trying to create a VLAN on 40+ networks using python with the Meraki SDK.

 

I would like to turn the networkid variable into a list or dictionary and run the code for each parameter within the list. After the parameter in the list is completed, I'd like to have a message printed saying the vlan was added successfully to the network. I am having trouble though turning each parameter of the list into a variable. Has anyone tried to do this? 

 

Example:

 

Variables

   networkid =['L_6464416461', 'L_1648946644']

   createVLAN = meraki.addvlan(apikey, networkid, vlanid, name, subnet, mxip,surpressprint=False)

 

With one parameter in the networkid, the script works, but when I add two +, it fails. I am new to python and all around scripting so i'm sure it is a simple setup, but it is proving difficult. Any help would be great!

 


networkid = ['L_6464416461', 'L_1648946644']
for network in networkid:
if networkid == 'L_1648946644':
break


My output is the following:
HTTP Status Code: 404 - No returned data
 
HTTP Status Code: 404 - No returned data
 
 
Process finished with exit code 0
CMNO, CCNA R+S
1 ACCEPTED SOLUTION
BrechtSchamp
Kind of a big deal

If networkid is the name you've given to your list and you do meraki.addvlan(apikey, networkid, vlanid, name, subnet, mxip,surpressprint=False), then it's just failing because that call isn't meant to accept a list for networkid.

 

What you'd need to do is meraki.addvlan(apikey, network, vlanid, name, subnet, mxip,surpressprint=False) inside your loop.

 

What's the reason for the break? Also, that networkid == 'L_1648946644' will never evaluate to true. Did you mean to write network == 'L_1648946644'?

View solution in original post

13 REPLIES 13
BrechtSchamp
Kind of a big deal

If networkid is the name you've given to your list and you do meraki.addvlan(apikey, networkid, vlanid, name, subnet, mxip,surpressprint=False), then it's just failing because that call isn't meant to accept a list for networkid.

 

What you'd need to do is meraki.addvlan(apikey, network, vlanid, name, subnet, mxip,surpressprint=False) inside your loop.

 

What's the reason for the break? Also, that networkid == 'L_1648946644' will never evaluate to true. Did you mean to write network == 'L_1648946644'?

Thanks @BrechtSchamp. the network ID was a fake one. I was using it as an example.
CMNO, CCNA R+S
Nash
Kind of a big deal

I think Brecht meant, within your loop, you're evaluating against the name of the list.

 

Not the name of the item you're checking.

 

Compare:

 

 

for item in list:
    if list == 'thing':
       print("List matched thing.")

 

 

Your snippet is doing the same, where item is "network" and list is "networkid"

 

Suggestion: name your list something like "networkIdList" or "network_id_list". Nice and clear what it is, but I suspect there's a Python programmer hissing at me right now.

BrechtSchamp
Kind of a big deal

Indeed :).

Thanks! changing it to network, allowed me to use the list successfully. The break was intended to stop the loop. I'd ultimately like to have the script do the following:

 

Create network VLAN

Print "VLAN Created for ID1"

Create next network VLAN

Print "VLAN Created for ID2"

.

.

.

Once the list is finished, print "VLAN Addition Complete."

 

Any additional thoughts on this?

CMNO, CCNA R+S

When you use for network in networkid you don't need a break to stop the loop. It'll stop automatically when it has iterated over all items. If you want to exclude certain ID's from the script, either remove them on beforehand or skip them with an if statement like @Nash mentioned in her post. It's rare that break and continue's are "good programming practice".

 

I'd also recommend that you make it easier on yourself by naming your variables more meaningfully. For example I'd change the name of the list to networkids and use networkid for the items in it. It'll make your code more readable/understandeable.

 

Now for your code, it should be something like:

 

for networkid in networkids:

    success = 0
    failure = 0

    try:
        result = meraki.addvlan(apikey, networkid, vlanid, name, subnet, mxip, surpressprint=False)

        # skip the following networks
        if networkid not in ['L_1648946644']:

            # try to create the VLAN
            if 200 <= int(result[0:3]) < 300: # check the returned status code
                success += 1
                print("VLAN created for ", networkid)

            else:
                failure += 1
                print("Something went wrong while creating VLAN for ", networkid, " returned message was: ", result)

    except ValueError as e:
        print("Exception occured while trying to create VLAN for ", networkid, " invalid VLAN ID")

    print('VLAN Addition Complete. Networks successful: ', success, ' Networks failed: ', failure)

 

 

Nash
Kind of a big deal

Can I suggest that when you're testing your code to make sure a loop works, you run a print statement?

 

In this case, I'd have done (with corrections as per Brecht):

 

networkid = ['ID#1', 'ID#2', 'ID#3']

for network in networkid:
    print("Checking network in networkid")
    if network == 'ID#1':
        print(f"Network: {network} equals ID#1")

 

Then when I run, I see my loop ran and I see if anything matched. For production code, I remove those print statements.

 

Sometimes I have sections of code with print statements after every line if I need to, including within any functions I've written.

PhilipDAth
Kind of a big deal
Kind of a big deal

>It's rare that break and continue's are "good programming practice".

 

I'll challenge you on that.

 

If you have nothing further to process then break is perfect.  A classic example I use is when iterating through organisations or networks - I "break" as soon as I have found the one that matches.  Why bother processing the rest?

 

If you have nested conditional logic then "continue" often saves having an addiitonal layer of nesting.

I knew I was going to get hit with counter examples. Curse you @PhilipDAth 🧛🏻‍

 

Why don't you fetch the orgs and networks you need directly by using their ID though?

 

The point I'm trying to make is that you have to be careful with them as it's easy to make mistakes. Your script will be running in an unexpected way and you might unwillingly be skipping important actions. And your script can be harder to understand as the flow is kind of interrupted.

Nash
Kind of a big deal


@BrechtSchamp wrote:

I knew I was going to get hit with counter examples. Curse you @PhilipDAth 🧛🏻‍

 

Why don't you fetch the orgs and networks you need directly by using their ID though?

 

The point I'm trying to make is that you have to be careful with them as it's easy to make mistakes. Your script will be running in an unexpected way and you might unwillingly be skipping important actions. And your script can be harder to understand as the flow is kind of interrupted.


This is where logically-designed pseudo code comes in for me. I write it to help my thinking, then adjust it into comments on my code.

 

No code is self documenting. I will fite anyone who argues. 🤣 Yes, I absolutely sometimes don't comment my code as much as I should.

>Why don't you fetch the orgs and networks you need directly by using their ID though?

 

You know the names before you start, but not the ID's usually.

 

This is a common bit of code I use to get the orgId.

	# Search for the org
	orgs = meraki.organizations.get_organizations()
	for org in orgs:
		if org['name'] == orgName:
			orgId=org['id']
			break;

 

"break" is elegant and simple.  You know there is going to be a 1:1 match, so there is no point continuing on once you have your answer.

 

KRobert
Head in the Cloud

Thanks everyone for your help! the change to the "network" from networkid as a variable definitely resolved the issue I was looking for. Thanks @BrechtSchamp for that. 

 

To note in regards to my messy coding, 1, I am a true script-kiddie at this point in time so my coding is rough to say the least 😀 and 2, This was a total test setup so clean code was not necessarily on top of mind.

 

The goal of this script was to deploy a new VLAN to 27 locations, create a new SSID, setup that SSID, and add features like VLAN tagging and Layer 2 Isolation. Creating a list of networks was really helpful, especially for future scripts so I will definitely use it going forward. 

 

I did discover though that my script change based on how the network is setup. An example would be an MX65w vs an MX with a MR positions the SSID network differently. Because of these differences, I changed my direction from list to input.

 

So far (its still as work in progress), I have the script ask what network ID to add, then it creates a vlan for that network. It then asks if the network has an access point. If so, it will run one script, if no, it will run another. Then it will ask if I want to do this again to a different network and the process repeats unless I say no.

 

Here it is:

from meraki import meraki
from pprint import pprint
import tkinter


#Organization Details
apikey = "<CustomAPIKey"
orgid = "<CustomOrgID"

#Network Details
mxip = "192.168.69.1"
name = "IoT_Network"
subnet = "192.0.0.0/24"
vlanid = "100"
ap_ssidnum = "3"
noap_ssidnum = "4"
enabled = "True"
authmode = "psk"
encryptionmode = "wpa"
psk = "<customPSK>"


#Create IoT VLAN and Add SSID Mac_IoT to unassigned 3 or 4
while True:
#Create and Update VLAN for network
NameNetwork = input('Enter Network ID:')
networkSSIDs4 = meraki.getssiddetail(apikey, NameNetwork, ap_ssidnum, suppressprint=False)
networkSSIDs5 = meraki.getssiddetail(apikey, NameNetwork, noap_ssidnum, suppressprint=False)
print({NameNetwork})
createVlan = meraki.addvlan(apikey,NameNetwork,vlanid,name,subnet,mxip,suppressprint=False)
updateVlan = meraki.updatevlan(apikey,NameNetwork,vlanid, name=None,subnet=None, mxip=None, fixedipassignments=None, reservedipranges=None, vpnnatsubnet=None, dnsnameservers="opendns", suppressprint=None,)

#If network has Access Point or Not
APQuestion = input('Does this network have an access point [y]/n:')
if APQuestion.lower() == 'y':
updateSSID = meraki.updatessid(apikey, NameNetwork, ap_ssidnum, name, enabled, authmode, encryptionmode, psk, suppressprint=False)
pprint(networkSSIDs4)
elif APQuestion.lower() == 'n':
updateSSID = meraki.updatessid(apikey, NameNetwork, noap_ssidnum, name, enabled, authmode, encryptionmode, psk, suppressprint=False)
pprint(networkSSIDs5)

restart = input("Do you want to make changes to another network [y]/n:")
if restart.lower() == 'n':
pprint('Thank you for using the network updater')
break

Let me know what you guys think and if I can do anything to make it simpler. My goal is to wrap it as an .exe as well (hence the tkinter, even though it is not in use.)

CMNO, CCNA R+S

Nice, that is a different approach for sure!

 

One thing I see you could easily optimize is the second question asking whether the network has an AP or not. You could just detect that yourself by calling the following endpoint:

BrechtSchamp_0-1576602689551.png

 

The python module has the call too:

def getnetworkdevices(apikey, networkid, suppressprint=False)

 

You could then iterate through those, check if there is an AP in there and base your configuration on that result. Then you can keep using the list and really automate it. Now it seems a bit laborious.

 

A little code snippet for you:

myNetworks = meraki.getnetworklist(apikey, '653657')

for network in myNetworks:
    deviceList = meraki.getnetworkdevices(apikey, network['id'])
    for device in deviceList:
        if(device['model'].startswith("MR")):
            print(network['id'], " contains APs")
            break

 

With a break, to please Philip.

 

Get notified when there are additional replies to this discussion.