
Managing about ~12 WLC's (and countless Routers/Switches/FW's/Servers etc.), I use Linux tools and scripts, like the one below, every day. Can't really imagine how much less efficient I'd be without them. When it comes to Python, I'm continually trying to learn & improve. I'd say not a week goes by where I don't think "Hmm, I should write a script for that".
Scripts and tools like this are not a replacement for PI or AMP, but for quick config or fast access to info (see examples) you can't beat it. The most complex command below takes no more than 10 seconds to type. Could you use your favorite NMS for this? Sure, but navigating to a web-page, logging in, clicking through the menu's, waiting for maps to load, running a report etc. etc. takes a LOT longer. I use GUI's as well, after all, some information is practically impossible to correlate otherwise; especially for WiFi management. While I'm not trying to create a GUI Vs. CLI death-match, the fact is: regardless of vendor, navigating the CLI will aid you in understanding the system and troubleshooting. Even my Palo Alto FW (almost entirely GUI driven) sends to Syslog...but that data is almost useless without grep, awk or similar. Ultimately, tools like this are just another one in the box.
Now, if you configure from a CLI, this may cause a "configuration mismatch" in your NMS. If a "mismatch" is possible, I think it's a bunk NMS model, but that's an entirely different topic.
Before getting in to the 'how', I'm going to start this off with some examples.
Examples
How many AP's are currently joined to WLC 13?$grep WLC-13 /tmp/wlc_aps | wc -l
Outputs:
940
I've got an issue affecting only 3600 model AP's...where are all my 3600's?
$ grep AP3602 /tmp/wlc_aps | sort
Outputs:
ap-beh-242-1 10.72.48.8 WLC-13 WiredMac=bc:16:65:6c:fa:c9 BaseRadio=f4:1f:c2:2:d6:50 UNLV AIR-CAP3602I-A-K9
ap-bhs-100-1 10.73.59.10 WLC-13 WiredMac=bc:16:65:6c:f7:64 BaseRadio=f4:1f:c2:2:9f:a0 UNLV AIR-CAP3602I-A-K9
*snip....*
I know the BSSID of an AP, but which AP is it? Leave off the last octet and grep for base-radio:
$ grep f4:1f:c2:8b:3e /tmp/wlc_aps
Outputs:
ap-bhs-130-1 10.73.58.72 WLC-13 WiredMac=bc:16:65:bd:90:9b BaseRadio=f4:1f:c2:8b:3e:60 UNLV AIR-CAP3602I
I want the AP name, IP Address and model number of every AP in the "Resnet" AP group:
$ grep Resnet /tmp/wlc_aps | awk '{print $1,$2,$7}'
Outputs:
ap-days-016-1 10.24.248.246 AIR-CAP3602I-A-K9
ap-ton-100e-1 10.24.251.159 AIR-CAP3602I-A-K9
ap-huh-121-1 10.24.240.68 AIR-CAP3602I-A-K9
*snip...*
Ok, that last one used AWK. AWK is great & powerful, but I only use it for one-liners. It's probably the tool I used most when navigating CLI's. If you just want to automate commands, and be much more efficient with any CLI, grep & awk are your friends. AWK looks strange at first, but the basics are super easy.
Now lets take it a step further, with some configuration examples:
Disable every 2.4GHz radio in the BEH building:
$ grep ap-beh /tmp/wlc_aps | awk '{print "config 802.11b disable",$1}'
Outputs:
config 802.11b disable ap-beh-449-1
config 802.11b disable ap-beh-342-1
*snip...*
Here's an example with multiple lines; answering a confirmation to reset every AP in the building, called "beh": (note, if you haven't guessed by now...my AP naming convention is "ap-<building>-<room number>-<increment>"
$ grep ap-beh /tmp/wlc_aps | awk '{print "config ap reset",$1;print "y"}'
Outputs:
config ap reset ap-beh-112-1
y
config ap reset ap-beh-242-2
y
*snip...*
Need to set the primary-base on all the AP's in a particular building?
$ grep ap-bhs /tmp/wlc_aps | awk '{print "config ap primary-base WLC-13",$1,"10.252.1.13"}'
Outputs:
config ap primary-base WLC-13 ap-bhs-100a-1 10.252.1.13
config ap primary-base WLC-13 ap-bhs-324-1 10.252.1.13
config ap primary-base WLC-13 ap-bhs-353-1 10.252.1.13
*snip...*
Just plugged in a new/test AP, but not sure which WLC it's joined to? In Cisco-world, AP's are part of the 'default-group' AP Group, so:
$ grep default-group /tmp/wlc_aps
Outputs:
AP0017.E095.3A28 10.247.228.241 WLC-8 WiredMac=0:17:e0:95:3a:28 BaseRadio=0:17:f:db:30:70 default-group AIR-LAP1242AG-A-K9
You can make this even easier with a package called xclip, which automatically pipes output to your clipboard (for pasting in to WLC). OSX users, you have 'pbcopy' so replace xclip w/ pbcopy in the following command:
grep ap-beh /tmp/wlc_aps | awk '{print "config 802.11b disable",$1}' | xclip
...now you just select your WLC terminal, and paste away. Side note, I think this makes xclip much more useful.
Necessary components (getting it to work)
UPDATE: I wrote a pure-python version (using PySNMP) so the below steps (installing net-snmp) is not required if you use this version. If you'd prefer to use net-snmp, continue with Step 1. below:
I wouldn't call it difficult, but there are some tools and steps you need to take to get net-snmp working. On a debian-based distribution:
I wouldn't call it difficult, but there are some tools and steps you need to take to get net-snmp working. On a debian-based distribution:
1. Install net-snmp & tools
- sudo apt-get install snmp snmp-mibs-downloader
2. Get the MIBS into the correct directory
- you can either DL them yourself or use the ones I've attached to the bottom of this post
- copy them into: /usr/share/snmp/mibs/
- Note, you man need to change ownership of them to your local user, if you copy them with sudo
3. Make sure net-snmp is working. Try the following, putting in your snmp RO string, and WLC IP address:
snmptable -CB -CH -v2c -Os -c <RO-String> <WLC-IP> AIRESPACE-WIRELESS-MIB::bsnAPTable
You should see a whole bunch of values (depending on how many AP's you have on the WLC) printed to your screen. That's the contents of the entire bsnAPTable.
You can either run the script manually, or do as I do, make it a nightly cron job. I've also added symlink in /usr/local/bin/ so I can run on-demand as necessary, by just typing 'list-aps':
- sudo ln -s /home/<username>/scripts/list-aps/list-aps.py /usr/local/bin/list-aps
The Script
I've commented it pretty heavily, so you should be able to read through it and make appropriate substitutions. The only real changes you 'need' to make are: snmp community (string) and your WLC IP address(s). Note, you need to have at least 1 AP joined to the WLC's you'r going to query.
I've included a link at the bottom of this post to download it directly.
Here's what to look for to get you started:
# Define your snmp RO String
RO_string = 'YOUR SNMP STRING HERE!'
# Define your WLC's by IP:
WLC_List = ['10.252.1.2','10.252.1.4','10.252.1.6']
More Options
The script currently queries for what I most often find useful. You could easily add in any of the following, which would require modifying only 2 lines of the script. I've bolded the values that I think are useful (outside of the ones already included).The options available from the MIB are:
BsnAPEntry ::=
SEQUENCE {
bsnAPDot3MacAddress MacAddress,
bsnAPNumOfSlots INTEGER,
bsnAPName OCTET STRING,
bsnApIpAddress IpAddress,
bsnAPLocation OCTET STRING,
bsnAPMonitorOnlyMode INTEGER,
bsnAPOperationStatus INTEGER,
bsnAPSoftwareVersion DisplayString,
bsnAPBootVersion DisplayString,
bsnAPPrimaryMwarName OCTET STRING,
bsnAPReset INTEGER,
bsnAPStatsTimer INTEGER,
bsnAPPortNumber INTEGER,
bsnAPModel DisplayString,
bsnAPSerialNumber DisplayString, <--great for inventory control
bsnAPClearConfig INTEGER,
bsnAPMirrorMode INTEGER,
bsnAPRemoteModeSupport INTEGER,
bsnAPType INTEGER,
bsnAPSecondaryMwarName OCTET STRING,
bsnAPTertiaryMwarName OCTET STRING,
bsnAPIsStaticIP INTEGER,
bsnAPNetmask IpAddress,
bsnAPGateway IpAddress,
bsnAPStaticIPAddress IpAddress,
bsnAPBridgingSupport INTEGER,
bsnAPGroupVlanName OCTET STRING,
bsnAPAdminStatus INTEGER,
bsnAPIOSVersion DisplayString,
bsnAPCertificateType INTEGER,
bsnAPEthernetMacAddress MacAddress
}
Other Systems
If you'd like to not store your RO string in cleartext, you can encrypt it with GPG (and decode that using your gpg-agent) which would only make the script slightly more complex. Using SNMPv3 should also be just a slight modification.You should be able to get this working on OSX, provided you have net-snmp working (just change the the first line to "#!/usr/local/bin/python", or wherever your python is located).
I suppose you could set this up on Windows, using Cygwin (Lipstick on a pig), but I haven't/will not ever try that.
This should be relatively easy to port to an Aruba WLC, possibly changing just 2 lines (the snmptable command & the 'writenlines' values). Until someone gives me an Aruba 620 I won't be able to test it.
Conclusion
The point here is that you don't 'need' to use this script, Python, or even Linux...but you DO need to use "something". By that I mean, you should learn a language. Personally, I have not yet mounted the SDN Unicorn, but even Bash is extremely helpful in my daily life as a network engineer.
Other examples: Use this same methodology to print number of clients per AP, use snmpset and raw_input to prompt the user for a command to apply to all WLC's, use PExpect & GPG to handle systems changes via SSH, etc. etc. If you'd find value in any of those, feel free to leave a comment and I'll write it up at some point.
These are the most simplistic examples, and just scratching the surface. Take a look at scapy for some real fun (packet injection).
Raw Files
AIRESPACE-WIRELESS-MIB.myAIRESPACE-REF-MIB.my
list-aps.py