"""
Nmcli parsers
=============
This file will parse the output of command line tools used to manage
NetworkManager.
Parsers provided by this module include:
NmcliDevShow - command ``/usr/bin/nmcli dev show``
--------------------------------------------------
NmcliConnShow - command ``/usr/bin/nmcli conn show``
----------------------------------------------------
"""
import re
from insights.core import CommandParser
from insights.core.exceptions import SkipComponent
from insights.core.plugins import parser
from insights.parsers import get_active_lines, parse_fixed_table
from insights.specs import Specs
[docs]@parser(Specs.nmcli_dev_show)
class NmcliDevShow(CommandParser, dict):
"""
.. warning::
This parser may be for a single device, please use
:py:class:`insights.combiners.nmcli.AllNmcliDevShow` instead for all the
devices.
This class will parse the output of command ``nmcli dev show``, and the information
will be stored in dictionary format.
NetworkManager displays all the devices and their current states along with network
configuration and connection status.
This parser works like a python dictionary, all parsed data can be accessed
via the ``dict`` interfaces.
Sample input for ``/usr/bin/nmcli dev show``::
GENERAL.DEVICE: em3
GENERAL.TYPE: ethernet
GENERAL.HWADDR: B8:AA:BB:DE:F8:B9
GENERAL.MTU: 1500
GENERAL.STATE: 100 (connected)
GENERAL.CONNECTION: em3
GENERAL.CON-PATH: /org/freedesktop/NetworkManager/ActiveConnection/1
WIRED-PROPERTIES.CARRIER: on
IP4.ADDRESS[1]: 10.16.184.98/22
IP4.GATEWAY: 10.16.187.254
IP4.DNS[1]: 10.16.36.29
IP4.DNS[2]: 10.11.5.19
IP4.DNS[3]: 10.5.30.160
IP4.DOMAIN[1]: abc.lab.eng.example.com
IP6.ADDRESS[1]: 2620:52:0:10bb:ba2a:72ff:fede:f8b9/64
IP6.ADDRESS[2]: fe80::ba2a:72ff:fede:f8b9/64
IP6.GATEWAY: fe80:52:0:10bb::fc
IP6.ROUTE[1]: dst = 2620:52:0:10bb::/64, nh = ::, mt = 100
GENERAL.DEVICE: em1
GENERAL.TYPE: ethernet
GENERAL.HWADDR: B8:AA:BB:DE:F8:BB
GENERAL.MTU: 1500
GENERAL.STATE: 30 (disconnected)
GENERAL.CONNECTION: --
GENERAL.CON-PATH: --
WIRED-PROPERTIES.CARRIER: off
GENERAL.DEVICE: em2
GENERAL.TYPE: ethernet
GENERAL.HWADDR: B8:AA:BB:DE:F8:BC
GENERAL.MTU: 1500
GENERAL.STATE: 30 (disconnected)
GENERAL.CONNECTION: --
GENERAL.CON-PATH: --
WIRED-PROPERTIES.CARRIER: off
Examples:
>>> type(nmcli_obj)
<class 'insights.parsers.nmcli.NmcliDevShow'>
>>> nmcli_obj['em3']['STATE']
'connected'
>>> nmcli_obj.get('em2')['HWADDR']
'B8:AA:BB:DE:F8:BC'
>>> sorted(nmcli_obj.connected_devices)
['em1', 'em2', 'em3']
"""
[docs] def parse_content(self, content):
if not content:
raise SkipComponent()
data = {}
per_device = {}
current_dev = ""
for line in get_active_lines(content):
if (not ("not found" in line or "Error" in line or "No such file" in line or "Warning" in line)):
if len(line.split(": ")) >= 2:
key, val = line.split(": ")
if "IP" in key:
proto = re.sub(r'\[|\]', r'', key.split('.')[1])
key = key.split('.')[0] + "_" + proto
else:
key = key.split('.')[1]
val = re.sub(r'\d+\s|\(|\)', r'', val.strip())
# Device configuration details starts here
if key == "DEVICE" and not current_dev:
current_dev = val
continue
elif key == "DEVICE" and current_dev:
data[current_dev] = per_device
current_dev = val
per_device = {}
continue
per_device.update({key: val})
if current_dev and per_device:
# Last device configuration details
data[current_dev] = per_device
if not data:
raise SkipComponent()
self.update(data)
self._con_dev = [k for k, v in data.items()
if 'STATE' in v and v['STATE'] == 'connected']
@property
def connected_devices(self):
"""(list): The list of devices who's state is connected and managed by NetworkManager"""
return self._con_dev
@property
def data(self):
"""(dict): Dict with the device name as the key and device details as the value."""
return self
[docs]@parser(Specs.nmcli_dev_show_sos)
class NmcliDevShowSos(NmcliDevShow):
"""
.. warning::
This parser may be for a single device, please use
:py:class:`insights.combiners.nmcli.AllNmcliDevShow` instead for all the
devices.
In some versions of sosreport, the ``nmcli dev show`` command is separated
to individual files for different devices. While in some versions, it's
still a whole file. The base class :py:class:`NmcliDevShow` could handle
both of them, except that the parsing results is stored into a list for
separated files.
"""
pass
[docs]@parser(Specs.nmcli_conn_show)
class NmcliConnShow(CommandParser):
"""
This file will parse the output of all the nmcli connections.
Sample configuration from a teamed interface in file ``/usr/bin/nmcli conn show``::
NAME UUID TYPE DEVICE
enp0s3 320d4923-c410-4b22-b7e9-afc5f794eecc ethernet enp0s3
virbr0 7c7dec66-4a8c-4b49-834a-889194b3b83c bridge virbr0
test-net f858b1cc-d149-4de0-93bc-b1826256847a ethernet --
Examples:
>>> type(static_conn)
<class 'insights.parsers.nmcli.NmcliConnShow'>
>>> static_conn.disconnected_connection
['test-net-1']
Attributes:
data (list): list of connections wrapped in dictionaries
"""
[docs] def parse_content(self, content):
try:
self.data = parse_fixed_table(content, heading_ignore=["NAME", "UUID", "TYPE", "DEVICE"])
except:
raise SkipComponent("Invalid Contents!")
self._disconnected_connection = []
for all_connection in self.data:
if all_connection['DEVICE'] == "--":
self._disconnected_connection.append(all_connection['NAME'])
@property
def disconnected_connection(self):
"""(list): It will return all the disconnected static route connections."""
return self._disconnected_connection