NetworkParse API
Parsing
Parse a network configuration file
To begin using networkparse
, typically an subclass of ConfigBase
will be
instantiated with the text of the configuration file. Currently, networkparse
has
support for:
Cisco IOS:
ConfigIOS
Cisco NX-OS:
ConfigNXOS
Fortinet:
ConfigFortigate
HP:
ConfigHPCommware
Junos:
ConfigJunos
The automatic parser, automatic()
may be a more effecient way to get started if
a single script may work work multiple configuration types.
Automatic Parsing
- networkparse.parse.automatic(config_content: str, *, include: List[str] = None, fallback: ConfigBase | None = None) ConfigBase
Based on the given configuration, guess the best parser.
Currently, this function can guess the following (ordered base on reliability)
ASA: reliable
FortiOS: probably reliable
JunOS: probably reliable
IOS: may catch non-IOS items, but is last thing checked
NX: untested, might work
- Parameters:
include – Only check the given types. Types are “asa”, “ios”, “nxos”, “fortios”, “hp”, and “junos”. By default all options will be checked. The names used match with the
name
of eachConfigBase
subclass.fallabck – If not match is found, use the specified class as a parser. This should be an object, not an instance (i.e.,
parse.ConfigIOS
vs.parse.ConfigIOS()
).
- Raises:
UnknownConfigError – The correct configuration type could not be determined
- Returns:
Parsed configuration
- Return type:
Base Configuration Manager
ConfigBase
will almost never be directly created, but it’s functionality is
shared by all other configuration classes. To avoid duplicate documentation, refer back
to this class for complete details on what a configuration type offers.
- class networkparse.parse.ConfigBase(name='base', original_lines: List[str] = None, comment_marker: str = '!', full_match_default: bool = True, indent_size_default: int = 2)
Common configuration base operations
ConfigBase
is really just a specializedConfigLineList
that can hold some settings and act like aConfigLine
in terms of having a parent (None
) and children.Refer to
ConfigLineList
for filtering and searching options after you’ve parsed a configuration file.- can_have_children(line: ConfigLine | str)
Checks if the given line is allowed to have child lines
Defaults to true, for compatibility with existing code
- property children: ConfigLineList
Allow for use of “.children” for consistency with
ConfigLine
Returns
self
, which is already aConfigLineList
. It is likely cleaner to not use this. I.E.:config = ConfigIOS(running_config_contents) # Prefer this config.filter("interface .+") # Only use this if it looks clearer in context config.children.filter("interface .+")
- comment_marker = '!'
Defaults to ! as the comment marker, following Cisco convention. If more complex comment checking is needed override is_comment()
- full_match = True
Default setting for
full_match
infilter
. Defaults to True to prevent a search from also matching the “no” version of the line.
- get_line(line_number) ConfigLine
Get a line by line-number
Note that if the given line numbers falls in the middle of a multi-line string, it may not be found, depending on how the individual parser represents it.
- Parameters:
line_number – Returns the line at the given line number.
- Raises:
IndexError – The given
line_number
does not exist in the config- Returns:
Line at the given line number
- Return type:
- property indent
The base config is never indented, at least for our purposes
- indent_size = 2
How far tree_display() should indent children. Has no effect on parsing
- name = 'base'
Name of configuration type, usable by scripts that support multiple configuration types.
- original_lines = None
Original configuration lines, before any parsing occured. The
line_number
from aConfigLine
will match up with this list
- parent = None
Exists to make walking up a parent tree easier–just look for parent=None to stop
Contrived example:
current_line = config.filter("no shutdown", depth=None) while current_line.parent is not None: print(current_line) current_line = current_line.parent
- property version: VersionNumber | None
Returns the version number of the configuration
This is intended to help with major version differences, i.e., IOS v12 vs. v15 differences. Generally it indentifies the version by looking for a line like “version 12.2”, although the details vary based on the parser in use. More details can be found on each of the base classes.
- Returns:
Floating-point version number (i.e. 12.1 or 15.4) or None if the version cannot be found
- Return type:
Optional[VersionNumber]
Cisco
- class networkparse.parse.ConfigIOS(config_content: str)
Parses Cisco IOS-style configuration into common config format
Supported command output:
show running-config
show running-config all
show startup-config
name
is set to “ios” for this parser.See
ConfigBase
for more information.- can_have_children(line: ConfigLine | str)
Checks if the given line is allowed to have child lines
- property version: VersionNumber | None
Returns the version number of the configuration
This is intended to help with v12 vs. v15 differences. It identifies the version by looking for a line like “version 12.2”.
- Returns:
Version number (i.e. 12 or 15) or None if the version cannot be found
- Return type:
Optional[VersionNumber]
- class networkparse.parse.ConfigNXOS(config_content: str)
Parses Cisco NX-OS-style configuration into common config format
Currently this parser completely defers to
ConfigIOS
.See
ConfigIOS
for more information.
- class networkparse.parse.ConfigASA(config_content: str)
Parses Cisco ASA-style configuration into common config format
Supported command output:
show running-config
show running-config all
show startup-config
name
is set to “asa” for this parser.See
ConfigBase
for more information.- property version: VersionNumber | None
Returns the major version number of the configuration
This is intended to help difference between major versions. It indentifies the version by looking for a line like “ASA Version 9.0(3)”.
- Returns:
Version number (i.e. 12.1 or 15.4) or None if the version cannot be found
- Return type:
Optional[VersionNumber]
Fortinet
- class networkparse.parse.ConfigFortigate(config_content: str)
Parses Fortinet-style configuration into common config format
Supported command output:
show full-configuration
name
is set to “fortios” for this parser.See
ConfigBase
for more information.- property version: VersionNumber | None
Returns the version number of the configuration
This is intended to help with v12 vs. v15 types of differences. It indentifies the version by looking for a line like “#config-version=FGVM64-6.2.0-FW-build0866-190328:opmode=0:vdom=0:user=admin”.
- Returns:
Float version number (i.e. 6.2) or None if the version cannot be found
- Return type:
Optional[VersionNumber]
HP
- class networkparse.parse.ConfigHPCommware(config_content: str)
Parses HP Commware-style configuration into common config format
name
is set to “hp” for this parser.See
ConfigBase
for more information.- property version: VersionNumber | None
Returns the major version number of the configuration
This is intended to help with v12 vs. v15 differences. It indentifies the version by looking for a line like “version 5.20, Release 1513P81”.
- Returns:
Version number (i.e. 5.20) or None if the version cannot be found
Juniper
- class networkparse.parse.ConfigJunos(config_content: str)
Parses a Juniper OS (Junos)-style configuration into common config format
Supported command outputs are:
show configuration
save
name
is set to “junos” for this parser.See
ConfigBase
for more information.
Parsing Utils
- class networkparse.parse.VersionNumber(major: int, minor: int = 0, revision: int = 0)
Firmware version number
- classmethod from_string(string) VersionNumber
Given a string containing a release number, returns a VersionNumber
Supported formats:
1.2.3
1.2
1.2(3)
Version string may appear anywhere in the given string.
- Parameters:
string – String to attempt to parse
- Returns:
VersionNumber with major, minor, and (if available) revision number set
- Return type:
Searching
Once a ConfigBase
has been created, searching is
typically done using ConfigLineList
and ConfigLine
.
- class networkparse.core.ConfigLineList(lines: List[ConfigLine] = None)
A searchable list of
ConfigLine
sThis class acts like a standard Python list, so indexed access via
[]
,len()
, etc. all work. See the Python 3 documentation on list for more methods.This class may not hold only
ConfigLine
items from the same parent–it can store anyConfigLine
, so be aware that iterating through aConfigLineList
does not necessarily mean all items have the same parent. In particular, after runningfilter()
orflatten()
the returned list will be a mixture of parents.- copy() List
Create a copy of this list
- Returns:
Copy of list.
ConfigLine
s are not duplicated.- Return type:
- exclude(regex: str, **kwargs) List
Calls
filter()
withinvert
=True
kwargs are passed through to
filter()
, see that for for argument descriptions.- Returns:
List with matching lines removed
- Return type:
- filter(regex: str, *, full_match: bool = None, ignore_case: bool = False, invert: bool = False, depth: int = 0, skip_comments: bool = True) List
Find all lines that match a regular expression
- Parameters:
regex – A string in Python’s regex format that will be checked against each line
full_match – If True, the regex must match the entire line (using Python’s
re.fullmatch
). If False, the regex can match any where in the line (usingre.search
). If None, uses the default for contained lines’config_manager
(typicallyTrue
).ignore_case – If True, the regex will be compiled with the flag
re.IGNORECASE
.invert – If True, excludes matched items from the list. Default is False, matching lines are returned in the new list
depth –
Controls whether searches look at direct descendents
depth = 0
: Line must be in this list, not a childdepth > 0
: Also search thechildren
of each line, up to the given depthdepth = None
: Search through entire tree
skip_comments – Controls whether search never returns comments. Default is True, meaning comment lines are never matched. Note that enabling this still means
regex
must match the line, including any comment characters.
- Returns:
New ConfigLineList with the filtered items. Returns an empty list if none are found.
- Return type:
- filter_with_child(child_regex: str, *, full_match: bool = None, ignore_case: bool = False, depth: int = 0) List
Find all lines that have a child that matches the given regex.
- Parameters:
child_regex – Regular expression that child line must match
full_match – Whether the regex must match the entire child line. See
filter()
for more details.ignore_case – If True, the regex will be compiled with the flag
re.IGNORECASE
. Seefilter()
for more details.depth – If is not 0, the child does not need to be a direct descendent. See
filter()
’sdepth
argument for more details.
- Returns:
New filtered list
- Return type:
For example, if this list has these items (children shown as well):
child child 1 child 2 child 3 child 4 child 5 child 6 child 7 child 8 child 9
Then
filter_with_child("child 4")
will return the list:child 3 child 4 child 5
If
depth
is not 0, the child does not need to be a direct descendent. Seefilter()
’sdepth
argument for more details. Given the example above, _with_child(“child 8”, depth=None)` will return the list:child 6 child 7 child 8 child 9
- filter_without_child(child_regex: str, *, full_match: bool = None, ignore_case: bool = False, depth: int = 0, skip_childless: bool = False) List
Find all lines that do not have a child that matches the given regex.
Follows the symmatics of
filter_with_child()
, see that function for more details.- Parameters:
skip_childless – If False (the default), a line that has no children will always be matched by this function.
- Returns:
New filtered list
- Return type:
- flatten(depth: int = None) List
Return a ConfigLineList of all of this list and the children
- Parameters:
depth – If
None
, returns all children, recursing as deeply as needed into the hierarchy (technically, limited to 500). Otherwise, flattens only the topdepth
levels.- Returns:
New
ConfigLineList
For example, say you have the structure:
level 1 level 2 level 3
flatten(depth=None)
returns:level 1 level 2 level 3
flatten(depth=1)
returns:level 1 level 2 level 3
- is_comment() bool
A list of lines is never comment
This exists to allow
is_comment()
to be called on a Config parser during setup, avoiding special cases.- Returns:
False
- one() ConfigLine
Returns the single ConfigLine in list
- Raises:
MultipleLinesError – There is more than one item in list.
NoLinesError – There are no items in list. Use
one_or_none()
to returnNone
if there are no items
- Returns:
First and only
ConfigLine
- one_or_none() ConfigLine
Returns the single ConfigLine in list
- Raises:
MultipleLinesError – There is more than one item in list. Use
one()
to raise an exception if there are no items- Returns:
First and only
ConfigLine
if there is one, otherwiseNone
- tree_display(initial_indent: int = 0, line_number: bool = False, child_count: bool = False) str
Print all lines in list with indents to show hierachy
- Parameters:
initial_indent – How many spaces to put before the first text on the line. If None, uses the “original” indent. See
tree_display()
for more details.line_number – Display original line numbers of each line
child_count – Display the number of children each line has
- Returns:
String of this and all child line items in an indented, human-readable format.
Also refer to
ConfigLine
’stree_display()
.Note
Top-level items may not all have the same parent, as a
ConfigLineList
can hold any combination of lines (even duplicates).
- class networkparse.core.ConfigLine(config_manager, parent, text: str, *, line_number: int = None, children: List = None, indent: str = None)
A line of a configuration file, which may or may not have children
Generally supports the same functions as Python strings.
- property can_have_children
Checks if this line is allowed to have children, according to the config manager
- children: ConfigLineList = None
Lines “under” this one–for example, lines 2 and 3 below would be children to line 1.
1. interface Ethernet0/1 2. no shutdown 3. switchport mode access
- config_manager: parse.ConfigBase = None
The
ConfigBase
-subclass which created the line and will be used for checking style-specific questions
- property depth: int
Returns how logically nested in the config this line is
For example, the config below has the
.depth
displayed next to each item:child 0 child 1 0 child 2 0 child 3 0 child 4 1 child 5 1 child 6 0 child 7 1 child 8 2 child 9 2
- Returns:
0 for top-level items, 1 or more for child items.
- endswith(sub, start=None, end=None)
See str.endswith
- get_next()
Returns next line in the configuration after this one
Returns None if this is the last line in the config.
- Returns:
ConfigLine that is next in the configuration file based on line number
- Return type:
- get_next_sibling()
Returns next sibling line in the configuration after this one
Returns None if there is no sibling item after this one. I.E., we would need to go up to the parent’s siblings to get the next line.
- Returns:
ConfigLine that is next in the configuration file that is logically a sibling of this one
- Return type:
- get_prev()
Returns previous line in the configuration after this one
Returns None if this is the first line in the config.
- Returns:
ConfigLine that is previous in the configuration file based on line number
- Return type:
- get_prev_sibling()
Returns previous sibling line in the configuration after this one
Returns None if there is no sibling item after this one. I.E., we would need to go up to the parent’s siblings to get the previous line.
- Returns:
ConfigLine that is previous in the configuration file that is logically a sibling of this one
- Return type:
- get_top() ConfigLine
Returns the top-level line that this child is a line of
May return the same line if it is a top-level item
- Returns:
Top-level ConfigLine with no parents (other than the full config itself)
- Return type:
- indent: str | None = None
Original raw indentation for line This is used internally by some parsers. If not used, it may be left as None
- is_comment() bool
Check if this line is a comment
- Returns:
True if line is a commment, False otherwise
- is_top() bool
Tests if this line is at the top-level of the configuration
- Returns:
True if the parent is the config itself, False otherwise
- Return type:
bool
- line_number: int | None = None
The line number in the original configuration file
- parent: parse.ConfigBase | ConfigLine = None
Parent block line (ie, might point to a line that’s interface Eth1/1) Could be a
ConfigBase
or anotherConfigLine
- partition(sep)
See str.partition
- rindex(sub, start=None, end=None)
See str.rindex
- rpartition(sep)
See str.rpartition
- rsplit(sep=None, maxsplit=-1)
See str.rsplit
- property siblings
Returns a
ConfigLineList
of all sibling linesDoes not include this line in the list. If you do want this line in the list, try
line.parent.children
.
- startswith(sub, start=None, end=None)
See str.startswith
- text: str = ''
Text of configuration line, not including any leading or trailing whitespace Generally, treat the
ConfigLine
itself as a string, rather than using.text
. For example:# Prefer these: parts = line.split() print(line) # To these: parts = line.text.split() print(line.text)
- tree_display(initial_indent: int = 0, line_number: bool = False, child_count: bool = False, internal_indent: int = 0) str
Print this line and child lines indented to show hierachy
- Parameters:
initial_indent – How many spaces to put before the first text on the line. If None, will use the “original” indent level–i.e., if this was a second-level item in the original config, it will be displayed with one indent before it.
line_number – Display original line numbers of each line
child_count – Display the number of children each line has
internal_indent – How many spaces to place after the line number
- Returns:
String of this and all child line items in an indented, human-readable format.
Exceptions
- class networkparse.core.MultipleLinesError
More than one line was found
- class networkparse.core.NoLinesError
No lines were found and at least one was expected