Friday, November 19, 2010

Switchport Verification Script

A commenter on my previous post directed me to the module CiscoConfParse which would have likely made this a much easier exercise.  Even so, this was a great exercise for me to go through, as it allowed me to learn a new programming language.
I’ll still post my solution to this problem, along with the supporting files.  The first file below is the Python script.  Running it with a –h option will show you the proper format for the parameters.  The supporting file “verification.txt” is also listed below.  It describes the format to use for the verification seed file.
If you happen to see anything wrong with this script, or room for improvement, please share your thoughts via comment or email.  I am always looking to learn, and I know there is room for improvement in my Python programming!
Jeremy

--------------------------
configcheck.py:
#
# configcheck.py - A script that verifies the existence or
#   absence of specific configuration lines in a Cisco switch config
#
import os
import re
import sys
import getopt
#
# Checks router interface configuration against a base config
#
def get_config_snmp():
    pass
def get_config_file(filename):
    """getconfig loads a router config and returns an array with individual lines"""
    if os.path.isfile(filename) == 0:
        sys.exit("ERROR: File does not exist")
    contents = []
    with open(filename, 'r') as file:
        for a in file: contents.append(a)
    file.closed
#
# Clear '/r', '/n', ' ' characters from file (to allow interchangeability between Unix/Windows)
#
    for x in range(0, len(contents)):
        if len(contents[x]) > 1:
            while contents[x][-1:] in ('\r', '\n', ' '): contents[x] = contents[x][:-1]
    return contents
def gethostname(config):
    """gethostname retrieves the device hostname from configuration file"""
    n = 0
    for n in range (0, len(config)):
        if len(config[n-1]) > 9:
            if config[n-1][:8] == "hostname":
                return config[n-1][9:]
    return "No Hostname Found"
def check_interfaces(config, int_type, verify_config):
    """check_interfaces retrieves interface configuration\
from the config and sends it to verify"""
    n = -1
    while n <= (len(config) - 2):
        n += 1
        if len(config[n]) > 9:
            if config[n][:9] == "interface":
                interface = []
                interface.append(config[n])
                n += 1
                while config[n][0] == ' ':
                    interface.append(config[n])
                    n += 1
                if re.search(int_type, interface[1]):
                    verify(interface, verify_config)
def verify(interface, verify_config):
    """verify takes an interface config and a list of required statements\
and verifies that each is present"""
    s = "\n\n! The Following Interface is Missing the Command(s) Below: \n\n"\
    + interface[0] + '\n' + interface[1]
    error = 0
    for a in verify_config:
        if a[1] == "!":
           b = " " + a[2:] + " "
           if interface.count(b):
               error += 1
               if b[1:2] == "no":
                   s += " " + b[3:] + '\n'
               else:
                   s += " no" + b + '\n'
        elif not interface.count(a):
            error += 1
            s += a + '\n'
#Print Error Interfaces
    if error: print s
#
# Main Program Body
#
#
# Process command-line arguments
#
config = []
verify_file = "verification.txt"
try:
    opts, args = getopt.getopt(sys.argv[1:], "hs:f:v:", ["help", "snmp=", "file=", "verify="])
except getopt.GetoptError, err:
    # print help information and exit:
    print str(err) # will print something like "option -a not recognized"
    sys.exit(2)
for o, a in opts:
    if o in ("-h", "--help"):
        sys.exit("\nOptions:\n\
-s, --snmp: Use SNMP to retrieve configuration (not implemented in this version)\n\
-f, --file: Load configuration from local file\n\
-v, --verify: Load verification file from local file (default is verification.txt)\n\
-h, --help: This message")
    elif o in ("-v", "--verify"):
        verify_file = a
    elif o in ("-s", "--snmp"):
        config = get_config_snmp(a)
        break
    elif o in ("-f", "--file"):
        config = get_config_file(a)
        break
    else:
        assert False, "unhandled option"
print "\n\n\nHostname (from configuration file): " + str(gethostname(config))
#
# Cycle through verification.txt to retrieve individual verification configuration
#
contents = []
with open(verify_file, 'r') as file:
    for a in file:
        if len(a) >= 4:
            if a[0] == '[':
                int_type = a[1:5]
            elif a[0] == ' ':
#
# Clear '/r', '/n', ' ' characters from file (to allow interchangeability between Unix/Windows)
#
                while a[-1:] in ('\r', '\n', ' '): a = a[:-1]
                contents.append(a)
            elif a[0] == "#":
                pass
        elif a[0] == "#":
            pass
        else:
            check_interfaces(config, int_type, contents)
            contents = []
file.closed
------------------------------------------------------
verification.txt:
#
# Comments begin with "#"
# Commands that must not be in the switchport configuration should begin with " !"
# Each interface type is headed with [XXXX]
# There is to be a blank line between each type
#
[ENDU]
switchport access vlan 10
switchport mode access
!mls qos trust dscp
service-policy input END-USER-IN
ip dhcp snooping limit rate 100
spanning-tree portfast
spanning-tree bpduguard enable
no logging event link-status
no snmp trap link-status
load-interval 30
switchport voice vlan 12
[SRVR]
!mls qos trust dscp
service-policy input SERVER-IN
ip dhcp snooping limit rate 100
spanning-tree portfast
spanning-tree bpduguard enable
logging event link-status
no snmp trap link-status
load-interval 30
[MPBX]
switchport mode access
mls qos trust dscp
flowcontrol receive desired
flowcontrol send off
ip dhcp snooping limit rate 100
logging event link-status
snmp trap link-status
load-interval 30
-------------
And to be complete, here is a sample switch configuration to use
sampleswitch.log:
!
hostname SampleSwitch
!
interface GigabitEthernet1/2
description ENDU; User A - Properly Configured
switchport
switchport access vlan 10
switchport mode access
switchport voice vlan 12
no logging event link-status
load-interval 30
wrr-queue bandwidth 5 25 70
wrr-queue queue-limit 5 25 40
wrr-queue random-detect min-threshold 1 80 100 100 100 100 100 100 100
wrr-queue random-detect min-threshold 2 80 100 100 100 100 100 100 100
wrr-queue random-detect min-threshold 3 50 60 70 80 90 100 100 100
wrr-queue random-detect max-threshold 1 100 100 100 100 100 100 100 100
wrr-queue random-detect max-threshold 2 100 100 100 100 100 100 100 100
wrr-queue random-detect max-threshold 3 60 70 80 90 100 100 100 100
wrr-queue cos-map 1 1 1
wrr-queue cos-map 2 1 0
wrr-queue cos-map 3 1 4
wrr-queue cos-map 3 2 2
wrr-queue cos-map 3 3 3
wrr-queue cos-map 3 4 6
wrr-queue cos-map 3 5 7
mls qos trust dscp
flowcontrol receive desired
flowcontrol send off
spanning-tree portfast
spanning-tree bpduguard enable
service-policy input END-USER-IN
ip dhcp snooping limit rate 100
no snmp trap link-status
!
interface GigabitEthernet1/3
description SRVR; Server A - Properly Configured
switchport
switchport access vlan 15
switchport mode access
logging event link-status
load-interval 30
wrr-queue bandwidth 5 25 70
wrr-queue queue-limit 5 25 40
wrr-queue random-detect min-threshold 1 80 100 100 100 100 100 100 100
wrr-queue random-detect min-threshold 2 80 100 100 100 100 100 100 100
wrr-queue random-detect min-threshold 3 50 60 70 80 90 100 100 100
wrr-queue random-detect max-threshold 1 100 100 100 100 100 100 100 100
wrr-queue random-detect max-threshold 2 100 100 100 100 100 100 100 100
wrr-queue random-detect max-threshold 3 60 70 80 90 100 100 100 100
wrr-queue cos-map 1 1 1
wrr-queue cos-map 2 1 0
wrr-queue cos-map 3 1 4
wrr-queue cos-map 3 2 2
wrr-queue cos-map 3 3 3
wrr-queue cos-map 3 4 6
wrr-queue cos-map 3 5 7
mls qos trust dscp
flowcontrol receive desired
flowcontrol send off
spanning-tree portfast
spanning-tree bpduguard enable
service-policy input SERVER-IN
ip dhcp snooping limit rate 100
no snmp trap link-status
!
interface GigabitEthernet1/4
description SRVR; Purposely Misconfigured
switchport
switchport trunk encapsulation dot1q
switchport mode trunk
logging event link-status
load-interval 30
wrr-queue bandwidth 5 25 70
wrr-queue queue-limit 5 25 40
wrr-queue random-detect min-threshold 1 80 100 100 100 100 100 100 100
wrr-queue random-detect min-threshold 2 80 100 100 100 100 100 100 100
wrr-queue random-detect min-threshold 3 50 60 70 80 90 100 100 100
wrr-queue random-detect max-threshold 1 100 100 100 100 100 100 100 100
wrr-queue random-detect max-threshold 2 100 100 100 100 100 100 100 100
wrr-queue random-detect max-threshold 3 60 70 80 90 100 100 100 100
wrr-queue cos-map 1 1 1
wrr-queue cos-map 2 1 0
wrr-queue cos-map 3 1 4
wrr-queue cos-map 3 2 2
wrr-queue cos-map 3 3 3
wrr-queue cos-map 3 4 6
wrr-queue cos-map 3 5 7
mls qos trust dscp
flowcontrol receive desired
flowcontrol send off
spanning-tree portfast
spanning-tree bpduguard enable
ip dhcp snooping trust
!
interface GigabitEthernet1/5
description ENDU; Purposely Misconfigured
switchport
switchport access vlan 30
switchport mode access
switchport voice vlan 125
no logging event link-status
load-interval 30
wrr-queue bandwidth 5 25 70
wrr-queue queue-limit 5 25 40
wrr-queue random-detect min-threshold 1 80 100 100 100 100 100 100 100
wrr-queue random-detect min-threshold 2 80 100 100 100 100 100 100 100
wrr-queue random-detect min-threshold 3 50 60 70 80 90 100 100 100
wrr-queue random-detect max-threshold 1 100 100 100 100 100 100 100 100
wrr-queue random-detect max-threshold 2 100 100 100 100 100 100 100 100
wrr-queue random-detect max-threshold 3 60 70 80 90 100 100 100 100
wrr-queue cos-map 1 1 1
wrr-queue cos-map 2 1 0
wrr-queue cos-map 3 1 4
wrr-queue cos-map 3 2 2
wrr-queue cos-map 3 3 3
wrr-queue cos-map 3 4 6
wrr-queue cos-map 3 5 7
snmp trap mac-notification change added
mls qos trust dscp
flowcontrol receive desired
flowcontrol send off
spanning-tree portfast
spanning-tree bpduguard enable
service-policy input END-USER-IN
ip dhcp snooping limit rate 100

1 comment:

Snapper said...

I've been attempting to do a bit of Python lately for network admin type tasks and just came across your blog. Thanks for sharing your script!