Parsers for ip command outputs

This module provides the following parsers:

IpAddr - command ip addr

RouteDevices - command ip route show table all

IpNeighParser - command ip neigh show nud all

IPs - command hostname -I

class insights.parsers.ip.IPs(context, extra_bad_lines=None)[source]

Bases: CommandParser

Reads the output of hostname -I and constructs a list of all assigned IP addresses. This command should only output IPV4 addresses and should not include localhost, but sometimes it does. The validation function removes those from the list.

Example output:

192.168.1.71 10.88.0.1 172.17.0.1 172.18.0.1 10.10.121.131

Resultant data structure:

[
    "192.168.1.71",
    "10.88.0.1",
    "172.17.0.1",
    "172.18.0.1",
    "10.10.121.131",
]
parse_content(content)[source]

This method must be implemented by classes based on this class.

class insights.parsers.ip.IpAddr(context, extra_bad_lines=None)[source]

Bases: CommandParser

This parser reads the output of ip addr into a dict whose key is the interface name. The information about this interface`addr` key is a array to store all address. Different type have different output. Peer ip and general interface have difference type.

Example output:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
    valid_lft forever preferred_lft forever

Resultant data structure:

{
    "index": 1,
    "physical_name": null,
    "qdisc": "noqueue",
    "name": "lo",
    "state": "UNKNOWN",
    "virtual": false,
    "mtu": 16436,
    "mac": "00:00:00:00:00:00",
    "flags": [
        "LOOPBACK",
        "UP",
        "LOWER_UP"
    ],
    "type": "loopback",
    "addr": [
        {
            "local_addr": null,
            "mask": "8",
            "p2p": false,
            "addr": "127.0.0.1"
        },
        {
            "local_addr": null,
            "mask": "128",
            "p2p": false,
            "addr": "::1"
        }
    ]
}

Examples

>>> for iface in shared[IpAddr]:
...     print 'Interface:', iface['name']
...     print 'State:', iface['state']
...     print 'Addresses:', ', '.join(a['addr'] for a in iface['addr'])
...
Interface: lo
State: UNKNOWN
Addresses: 127.0.0.1, ::1
Interface: eth7
State: DOWN
Addresses:
Interface: tunl1
State: DOWN
Addresses: 172.30.0.1
Interface: bond1.57
State: UP
Addresses:10.192.4.171, fe80::211:3fff:fee2:f59e, 2001::211:3fff:fee2:f59e
Interface: ip.tun2
State: UNKNOWN
Addresses: 192.168.122.6
property active

List of interfaces with ‘UP’ set in their flags.

Type:

(list)

parse_content(content)[source]

This method must be implemented by classes based on this class.

class insights.parsers.ip.IpLinkInfo(context, extra_bad_lines=None)[source]

Bases: IpAddr

This parser parses the output of ip -s link command, which shows the data link layer stats of network devices, like packets received, packets dropped, link state, mtu.

Example output:

1: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
            link/ether 08:00:27:4a:c5:ef brd ff:ff:ff:ff:ff:ff
            RX: bytes  packets  errors  dropped overrun mcast
            1113685    2244     0       0       0       0
            TX: bytes  packets  errors  dropped carrier collsns
            550754     1407     0       0       0       0

Resultant output:

{
    "index": 1,
    "physical_name": null,
    "name": "enp0s3",
    "flags": [
        "BROADCAST",
        "MULTICAST",
        "UP",
        "LOWER_UP"
    ],
    "addr":[]
    "mtu": 1500,
    "qdisc": "pfifo_fast",
    "state": "UP",
    "mode": "DEFAULT",
    "qlen": 1000,
    "mac": "08:00:27:4a:c5:ef",
    "brd": "ff:ff:ff:ff:ff:ff",
    "rx_bytes": 1113685,
    "rx_packets": 2244,
    "rx_errors": 0,
    "rx_dropped": 0,
    "rx_overrun": 0,
    "rx_mcast": 0,
    "tx_bytes": 550754,
    "tx_packets": 1407,
    "tx_errors": 0,
    "tx_dropped": 0,
    "tx_carrier": 0,
    "tx_collsns": 0
}

Examples

>>> type(ip_link)
<class 'insights.parsers.ip.IpLinkInfo'>
>>> for iface in ip_link:
...     print 'Interface:', iface['name']
...     print 'State:', iface['state']
...     print 'RX packets:', iface['rx_packets']
...     print 'RX dropped:', iface['rx_dropped']
...     print 'TX packets:', iface['tx_packets']
...     print 'TX dropped:', iface['tx_dropped']
...
Interface: lo
State: UNKNOWN
RX packets: 98
RX dropped: 0
TX packets: 10
TX dropped: 0
Interface: enp0s3
State: UP
RX packets: 2244
RX dropped: 0
TX packets: 1407
TX dropped: 0
Interface: enp0s8
State: UP
RX packets: 1
RX dropped: 0
TX packets: 4
TX dropped: 0
Interface: enp0s9
State: UP
RX packets: 8
RX dropped: 0
TX packets: 12
TX dropped: 0
class insights.parsers.ip.IpNeighParser(context, extra_bad_lines=None)[source]

Bases: CommandParser

This parser takes the output of ip neigh show nud all results for ARP and NDISC cache entries and reads them into a dictionary of results keyed on the name of the IP address. Each item is a dictionary of the properties of that address record in the ARP table. Fields usually include:

  • dev - the device the address was seen on

  • lladdr - the link level (MAC) address associated with the IP

  • nud - the Neighbour Unreachability Detection result, which is one of the following values:

    • permanent - the neighbour is permanently valid

    • noarp - the neighbour is valid and does not need revalidation

    • reachable - the neighbour is valid until its lifetime expires

    • stale - the neighour has not been seen in a while and its lifetime has expired, but it may still be valid

    • failed - the neighbour resolution has failed

This class deals with both IPv4 and IPv6 records, and is subclassed to the two related parsers.

Sample (IPv4) input data:

172.17.0.19 dev docker0  FAILED
172.17.42.1 dev lo lladdr 00:00:00:00:00:00 NOARP

Examples

>>> neighb4 = shared[Ipv4Neigh]
>>> '192.168.0.1' in neighb4
False
>>> '172.17.0.19' in neighb4
True
>>> neighb4['172.17.0.19']['dev']
'docker0'
>>> neighb4['172.17.42.1']['lladdr']
'00:00:00:00:00:00'
parse_content(content)[source]

Parse the lines if the ip neighbor output. Each line is split up into words on spaces, and must meet the following criteria:

  • there must be at least two words on the line

  • the first word must be a valid IP (v4 or v6) address

  • the last word must be a valid Neighbour Unreachability Detection state

  • the remaining words must be in pairs - these are then combined into key-value pairs for a dictionary.

Each line is then stored in a dictionary by the address (as a string). The address as parsed by the ipaddress module is stored in the addr item in the dictionary, for convenience.

class insights.parsers.ip.IpNeighShow(context, extra_bad_lines=None)[source]

Bases: IpNeighParser

Class to parse ip neigh show or ip -s -s neigh show command output.

class insights.parsers.ip.Ipv4Neigh(context, extra_bad_lines=None)[source]

Bases: IpNeighParser

Class to parse ip -4 neigh show nud all command output.

class insights.parsers.ip.Ipv6Neigh(context, extra_bad_lines=None)[source]

Bases: IpNeighParser

Class to parse ip -6 neigh show nud all command output.

class insights.parsers.ip.RouteDevices(context, extra_bad_lines=None)[source]

Bases: CommandParser

This parser reads the output of the command ip route show table all and provides access to the routing table.

Each object in these properties is stored as a Route object, which has as properties the various parts of the route line. Route objects will always include these properties (all defaulting to None):

  • type - the type of route (e.g. ‘throw’)

  • dev - the device routed through (e.g. ‘eth0’)

  • via - the external address routed through, or None if direct

  • netmask - the CIDR notation of the network as a string (e.g. ‘24’)

  • table - the routing table, or None if not given.

Destinations given as broadcast, throw, unreachable, prohibit, blackhole and nat are discarded.

Destinations given as unicast, multicast and local are considered.

Properties:

by_device (dict): routes by device (e.g. 'eth0').
by_type (dict): routes by table type (e.g. 'throw', default = 'None').
by_table (dict): routes by table (e.g. 'mgmt', default = 'None').

Sample routing table:

default via 192.168.1.254 dev enp0s25
10.0.0.0/8 via 10.64.54.1 dev tun0  proto static  metric 50
10.64.54.0/23 dev tun0  proto kernel  scope link  src 10.64.54.44  metric 50
66.187.239.220 via 192.168.23.250 dev enp0s25  proto static
192.168.0.0/24 dev enp0s25  proto kernel  scope link  src 192.168.1.37
192.168.122.0/24 dev virbr0  proto kernel  scope link  src 192.168.122.1

Examples

>>> routes = shared[RouteDevices]
>>> 'default' in routes
True
>>> '10.64.54.0/23' in routes
False
>>> len(routes['10.64.54.0/23']) # Multiple routes possible, esp. for default
1
>>> tunnel = routes['10.64.54.0/23'][0]
>>> tunnel.dev
'tun0'
>>> tunnel.proto
'kernel'
>>> len(routes.by_device['tun0'])
2
>>> routes.by_device['tun0'][1] == tunnel
True
property by_prefix

The dictionary of routes by prefix (e.g. ‘192.168.0.0/24’).

Type:

(Route)

property defaults

The list of default routes.

Type:

(list)

ifaces(ip)[source]

Given an IP address, choose the best iface name to return. If there are multiple routes that match, then the one with the most specific netmask will be returned. There may be multiple interfaces that serve this route so it returns a list. If there are default routes, then these are used if a route is not found. If no default routes are found, then return None.

Returns:

Device names that serve this network, or None if not found.

Return type:

(list)

Examples

>>> ip_table = shared[RouteDevices]
>>> iface = ip_table.ifaces(YOUR_IP_ADDRESS_STRING)
parse_content(content)[source]

Read the routing table and construct the routes and data properties.