Skip to main content

Parse through Cisco IOS-style configurations and retrieve portions of the config using a variety of query methods

Project description

INTRO
=====

ciscoconfparse is a Python package for parsing through Cisco IOS-style
configurations and retrieving portions of the config based on a variety of
query methods.

The package will process an IOS-style config and break it into a set of
linked parent / child relationships. Then you issue queries against these
relationships using a familiar family syntax model. Queries can either be in
the form of a simple string, or you can use regular expressions. The API
provides powerful query tools, including the ability to find all parents that
have or do not have children matching a certain criteria. This means it is
easy to find the interface names of all layer2 trunks in a Catalyst 6500, or
retrieve a list of all interfaces with cdp disabled. Until this package, I
know of no simple config-parsing APIs to do the same; it has traditionally
been considered the domain of screen-scraping. In conjunction with python's
sophisticated set-manipulation capabilities, your imagination is the limit.

The package also provides a set of methods to query and manipulate the
IOSConfigLine objects themselves. This gives you a flexible mechanism to build
your own custom queries, because the IOSConfigLine objects store all the
parent / child hierarchy in them.

Examples of config family relationships are shown below...

Line01:policy-map QOS_1
Line02: class GOLD
Line03: priority percent 10
Line04: class SILVER
Line05: bandwidth 30
Line06: random-detect
Line07: class default
Line08:!
Line09:interface Serial 1/0
Line10: encapsulation ppp
Line11: ip address 1.1.1.1 255.255.255.252
Line12:!
Line13:access-list 101 deny tcp any any eq 25 log
Line14:access-list 101 permit ip any any

parents: 01, 02, 04, 09
children: of 01 = 02, 04, 07
of 02 = 03
of 04 = 05, 06
of 09 = 10, 11
siblings: 02, 04, 07
05, 06
10, 11
oldest_ancestors: 01, 09
families: 01, 02, 03, 04, 05, 06, 07
09, 10, 11
family_endpoints: 07, 11


Note that 01, 09, 13 and 14 are not considered siblings, nor are they part of
the same family. In fact, 13 and 14 do not belong to a family at all; they
have no children.

Methods
-------

The package provides several types of methods:

1. Query methods returning a list of text lines.
1.1 find_lines(self, linespec, exactmatch=False, ignore_ws=False):
1.2 find_children(self, linespec, exactmatch=False, ignore_ws=False):
1.3 find_all_children(self, linespec, exactmatch=False, ignore_ws=False):
1.4 find_blocks(self, blockspec, exactmatch=False, ignore_ws=False):
1.5 find_parents_w_child(self, parentspec, childspec, ignore_ws=False):
1.6 find_parents_wo_child(self, parentspec, childspec, ignore_ws=False):
1.7 req_cfgspec_all_diff(self, cfgspec):
1.8 req_cfgspec_excl_diff(self, linespec, uncfgspec, cfgspec):


2. Query methods returning a list of IOSConfigLine objects.
2.1 find_line_OBJ(self, linespec):
2.2 find_sibling_OBJ(self, lineobject):
2.3 find_child_OBJ(self, lineobject):
2.4 find_all_child_OBJ(self, lineobject):
2.5 find_parent_OBJ(self, lineobject):

3. Methods for manipulating IOSConfigLine objects
3.1 unique_OBJ(self, objectlist):
3.2 objects_to_lines(self, objectlist):
3.3 objects_to_uncfg(self, objectlist, unconflist):

4. Methods attached to IOSConfigLine objects
4.1 parent(self):
4.2 children(self):
4.3 has_children(self):
4.4 child_indent(self):
4.5 oldest_ancestor(self):
4.6 family_endpoint(self):
4.7 linenum(self):
4.8 text(self):
4.9 uncfgtext(self):


5. Methods for parsing the configuration: I won't bother explaining here...
You have the source if you are interested :-).


BASIC USAGE
===========

#!/usr/bin/env python
from ciscoconfparse import CiscoConfParse

parse = CiscoConfParse("/tftpboot/bucksnort.conf")

# Return a list of all ATM interfaces and subinterfaces
#
atm_intfs = parse.find_lines("^interface\sATM")

# Return a list of all interfaces with a certain QOS policy
#
qos_intfs = parse.find_parents_w_child("^interf", "service-policy QOS_01")

# Return a list of all active interfaces (i.e. not shutdown)
#
active_intfs = parse.find_parents_wo_child("^interf", "shutdown")

# Find all interfaces that have voice configured, if they are trusting dscp
# build a new config to trust cos
#
# You must put a caret (^) sign in front of "interface" below... otherwise you will get matches
# for any command with interface in the syntax. ^ is a regular expression to match the beginning
# of a line.
#
newcfg = list()
voice_intfs = parse.find_parents_w_child("^interface", "switchport voice")
for intf in voice_intfs:
famobj = CiscoConfParse(parse.find_children(intf, exactmatch=True))
if(famobj.find_lines("mls qos trust dscp")):
newcfg.append(intf)
newcfg.append(" mls qos trust cos")


The examples/ directory in the distribution contains more usage cases,
including sample configs to parse.


ADVANCED USAGE
==============

When enforcing configuration standards, the req_cfgspec_excl_diff() method is
very useful. The following example illustrates how you can require three
syslog servers and unconfigure those you don't want to use.

#!/usr/bin/env python
from ciscoconfparse import CiscoConfParse

## This is the configuration we start with
config = [
'logging trap debugging',
'logging 172.28.26.15',
]
p = CiscoConfParse(config)
## This is the configuration we need to enforce...
required_lines = [
"logging 172.16.1.5",
"logging 1.10.20.30",
"logging 192.168.1.1",
]
# lines matching linespec are enforced
linespec = "logging\s+\d+\.\d+\.\d+\.\d+"
# unconfspec is a template for *how* we remove non-conforming lines...
unconfspec = linespec
diffs = p.req_cfgspec_excl_diff(linespec, unconfspec,
required_lines)


When you run this code, you will get the following lines stored in diffs...

no logging 172.28.26.15
logging 172.16.1.5
logging 1.10.20.30
logging 192.168.1.1

If you apply this to the router, now your syslog statements conform to your
expectations.

FAQ
===

Q1: Is there a way to use this module with perl?
A1: Yes, I do this myself. Install the python package as you normally would
and import it into perl with Inline.pm and Inline::Python from CPAN.

Q2: When I use find_children("interface GigabitEthernet3/2"), I'm getting all
interfaces beginning with 3/2, including 3/21, 3/22, 3/23 and 3/24. How can I
limit my results?
A2. There are two ways... the simplest is to use the 'exactmatch' option...
find_children("interface GigabitEthernet3/2", exactmatch=True). Another way is
to utilize regex expansion that is native to many methods...
find_children("interface GigabitEthernet3/2$")


AUTHOR
======

David Michael Pennington


THANKS
------

Thanks to David Muir Sharnoff for his suggestion about making a special case
for IOS banners. Thanks to Alan Cownie for his API suggestions. Thanks to
everyone in advance for their bug reports and patience. Sola Dei Gloria.

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ciscoconfparse-0.9.0.tar.gz (46.9 kB view hashes)

Uploaded source

Built Distribution

ciscoconfparse-0.9.0-py2.6.egg (24.4 kB view hashes)

Uploaded 2 6

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page