SkillAgentSearch skills...

Ciscoconfparse

Parse, Audit, Query, Build, and Modify Arista / Cisco / Juniper / Palo Alto / F5 configurations.

Install / Use

/learn @mpenning/Ciscoconfparse

README

ciscoconfparse

[![git commits][41]][42] [![Version][2]][3] [![Downloads][6]][7] [![License][8]][9]

[![SonarCloud][51]][52] [![SonarCloud Maintainability Rating][53]][54] [![SonarCloud Lines of Code][55]][56] [![SonarCloud Bugs][59]][60] [![SonarCloud Code Smells][57]][58] [![SonarCloud Tech Debt][61]][62]

[![Snyk Package Health][37]][38]

Important: ciscoconfparse2

ciscoconfparse is End of Life

As of December 14, 2023 [ciscoconfparse2][64] is released; this is equivalent to version 2.0 of [ciscoconfparse][17], but [ciscoconfparse2][64] is a different PYPI project.

You should upgrade; here's why, [ciscoconfparse2][64]:

  • It supports all major network vendor text configuration files (Arista, Cisco, F5, Juniper, Palo Alto)
  • It supports searching across any number of configuration levels ([ciscoconfparse][17] only supports two config levels : a parent and child)
  • It adds a string methods so you don't need to use regex matching if you don't want to
  • It adds a CLI command
  • Revamped documentation
  • It simplifies the user interface and fixes broken [ciscoconfparse][17] default parameters (this could require changing old scripts using the original API)
  • It intentionally uses a new python import to minimize confusion between itself and the original

NOTE [ciscoconfparse2][64] deprecates many legacy [ciscoconfparse][17] APIs; overall this is a good thing because [ciscoconfparse2][64] is easier to use. As such, test your code before using [ciscoconfparse2][64] as a drop-in replacement.

Introduction: What is ciscoconfparse?

Short answer: ciscoconfparse is a [Python][10] library that helps you quickly answer questions like these about your Cisco configurations:

  • What interfaces are shutdown?
  • Which interfaces are in trunk mode?
  • What address and subnet mask is assigned to each interface?
  • Which interfaces are missing a critical command?
  • Is this configuration missing a standard config line?

It can help you:

  • Audit existing router / switch / firewall / wlc configurations
  • Modify existing configurations
  • Build new configurations

Speaking generally, the library examines an IOS-style config and breaks it into a set of linked parent / child relationships. You can perform complex queries about these relationships.

[![Cisco IOS config: Parent / child][11]][11]

Generic Usage

The following code will parse a configuration stored in exampleswitch.conf and select interfaces that are shutdown.

In this case, the parent is a line containing interface and the child is a line containing the word shutdown.

from ciscoconfparse import CiscoConfParse

parse = CiscoConfParse('exampleswitch.conf', syntax='ios')

for intf_obj in parse.find_parent_objects('^interface', '^\s+shutdown'):
    print("Shutdown: " + intf_obj.text)

The next example will find the IP address assigned to interfaces.

from ciscoconfparse import CiscoConfParse

parse = CiscoConfParse('exampleswitch.conf', syntax='ios')

for ccp_obj in parse.find_objects('^interface'):

    intf_name = ccp_obj.re_match_typed('^interface\s+(\S.+?)$')

    # Search children of all interfaces for a regex match and return
    # the value matched in regex match group 1.  If there is no match,
    # return a default value: ''
    intf_ip_addr = ccp_obj.re_match_iter_typed(
        r'ip\saddress\s(\d+\.\d+\.\d+\.\d+)\s', result_type=str,
        group=1, default='')
    print(f"{intf_name}: {intf_ip_addr}")

Cisco IOS Factory Usage

CiscoConfParse has a special feature that abstracts common IOS / NXOS / ASA / IOSXR fields; at this time, it is only supported on those configuration types. You will see factory parsing in CiscoConfParse code as parsing the configuration with factory=True. A fraction of these pre-parsed Cisco IOS fields follows; some variables are not used below, but simply called out for quick reference.

from ciscoconfparse import IPv4Obj, IPv6Obj
from ciscoconfparse import CiscoConfParse

##############################################################################
# Parse an example Cisco IOS HSRP configuration from:
#     tests/fixtures/configs/sample_08.ios
#
# !
# interface FastEthernet0/0
#  ip address 172.16.2.1 255.255.255.0
#  ipv6 dhcp server IPV6_2FL_NORTH_LAN
#  ipv6 address fd01:ab00::/64 eui-64
#  ipv6 address fe80::1 link-local
#  ipv6 enable
#  ipv6 ospf 11 area 0
#  standby 110 ip 172.16.2.254
#  standby 110 ipv6 autoconfig
#  standby 110 priority 150
#  standby 110 preempt delay minimum 15
#  standby 110 track Dialer1 75
#  standby 110 track FastEthernet 0/1
#  standby 110 track FastEthernet1/0 30
#  standby 111 ip 172.16.2.253
#  standby 111 priority 150
#  standby 111 preempt delay minimum 15
#  standby 111 track Dialer1 50
#
##############################################################################
parse = CiscoConfParse('tests/fixtures/configs/sample_08.ios', syntax='ios', factory=True)
for ccp_obj in parse.find_objects('^interface'):

    # Skip if there are no HSRPInterfaceGroup() instances...
    if len(ccp_obj.hsrp_interfaces) == 0:
        continue

    # Interface name, such as 'FastEthernet0/0'
    intf_name = ccp_obj.name

    # Interface description
    intf_description = ccp_obj.description

    # IPv4Obj
    intf_v4obj = ccp_obj.ipv4_addr_object

    # IPv4 address object: ipaddress.IPv4Address()
    intf_v4addr = ccp_obj.ipv4_addr_object.ip

    # IPv4 netmask object: ipaddress.IPv4Address()
    intf_v4masklength = ccp_obj.ipv4_addr_object.masklength

    # set() of IPv4 secondary address/prefixlen strings
    intf_v4secondary_networks = ccp_obj.ip_secondary_networks

    # set() of IPv4 secondary address strings
    intf_v4secondary_addresses = ccp_obj.ip_secondary_addresses

    # List of HSRP IPv4 addrs from the ciscoconfpasre/models_cisco.py HSRPInterfaceGroup()
    intf_hsrp_addresses = [hsrp_grp.ip for hsrp_grp in ccp_obj.hsrp_interfaces]

    # A bool for using HSRP bia mac-address...
    intf_hsrp_usebia = any([ii.use_bia for ii in ccp_obj.hsrp_interfaces])

    ##########################################################################
    # Print a simple interface summary
    ##########################################################################
    print("----")
    print(f"Interface {ccp_obj.interface_object.name}: {intf_v4addr}/{intf_v4masklength}")
    print(f"  Interface {intf_name} description: {intf_description}")

    ##########################################################################
    # Print HSRP Group interface tracking information
    ##########################################################################
    print("")
    print(f"  HSRP tracking for {set([ii.interface_name for ii in ccp_obj.hsrp_interfaces])}")
    for hsrp_intf_group in ccp_obj.hsrp_interfaces:
        group = hsrp_intf_group.hsrp_group
        # hsrp_intf_group.interface_tracking is a list of dictionaries
        if len(hsrp_intf_group.interface_tracking) > 0:
            print(f"  --- HSRP Group {group} ---")
            for track_intf in hsrp_intf_group.interface_tracking:
                print(f"    --- Tracking {track_intf.interface} ---")
                print(f"    Tracking interface: {track_intf.interface}")
                print(f"    Tracking decrement: {track_intf.decrement}")
                print(f"    Tracking weighting: {track_intf.weighting}")


    ##########################################################################
    # Break out inidividual interface name components
    #   Example: 'Serial3/4/5.6:7 multipoint'
    ##########################################################################
    # The base ciscoconfparse/ccp_util.py CiscoInterface() instance
    intf_cisco_interface = ccp_obj.interface_object
    # The ciscoconfparse/ccp_util.py CiscoInterface() name, 'Serial3/4/5.6:7 multipoint'
    intf_name = ccp_obj.interface_object.name
    # The ciscoconfparse/ccp_util.py CiscoInterface() prefix, 'Serial'
    intf_prefix = ccp_obj.interface_object.prefix
    # The ciscoconfparse/ccp_util.py CiscoInterface() digit separator, '/'
    digit_separator = ccp_obj.interface_object.digit_separator or ""
    # The ciscoconfparse/ccp_util.py CiscoInterface() slot, 3
    intf_slot = ccp_obj.interface_object.slot or ""
    # The ciscoconfparse/ccp_util.py CiscoInterface() card, 4
    intf_card = ccp_obj.interface_object.card or ""
    # The ciscoconfparse/ccp_util.py CiscoInterface() card, 5
    intf_port = ccp_obj.interface_object.port
    # The ciscoconfparse/ccp_util.py CiscoInterface() subinterface, 6
    intf_subinterface = ccp_obj.interface_object.subinterface or ""
    # The ciscoconfparse/ccp_util.py CiscoInterface() channel, 7
    intf_channel = ccp_obj.interface_object.channel or ""
    # The ciscoconfparse/ccp_util.py CiscoInterface() interface_class, 'multipoint'
    intf_class = ccp_obj.interface_object.interface_class or ""

    ##########################################################################
    # Extract all IPv4Obj() with re_match_iter_typed()
    ##########################################################################
    _default = None
    for _obj in ccp_obj.children:
        # Get a dict() from re_match_iter_typed() by caling it with 'groupdict'
        intf_dict = _obj.re_match_iter_typed(
            # Add a regex match-group called 'v4addr'
            r"ip\s+address\s+(?P<v4addr>\S.+?\d)\s*(?P<secondary>secondary)*$",
            # Cast the v4addr regex match group as an IPv4Obj() type
            groupdict={"v4addr": IPv4Obj, "secondary": str},
            # Default to None if there is no regex match
            default=_default,
        )
        intf_ipv4obj = intf_dict["v4addr"]

    ##########################################################################
    # Extract all IPv6Obj() with re_match_iter_typed()
    #####################
View on GitHub
GitHub Stars839
CategoryDevelopment
Updated22d ago
Forks214

Languages

Python

Security Score

100/100

Audited on Mar 8, 2026

No findings