"""
Parsers for ``modinfo <module_name>``
=====================================
KernelModulesInfo - Command ``modinfo filtered_modules``
--------------------------------------------------------
"""
from insights.core import CommandParser
from insights.core.exceptions import SkipComponent
from insights.core.plugins import parser
from insights.specs import Specs
[docs]class ModInfo(dict):
"""
Base class for the information about a kernel module, the module
info will be stored in dictionary format. Besides of that, the following
utility properties are provided as well.
"""
[docs] @classmethod
def from_content(cls, content):
"""
A classmethod to generated a `ModInfo` object from the given `content`
list. Two more keys `module_name` and `module_deps` will be created as
well per the `content`.
Raises:
SkipComponent: When nothing need to check to a dict.
"""
if not content:
raise SkipComponent("No Contents")
data = {}
for line in content:
line = line.strip()
if ':' in line:
key, value = [l.strip() for l in line.split(':', 1)]
if key not in data:
data[key] = value
else:
old_val = data[key]
data[key] = [old_val] if isinstance(old_val, str) else old_val
data[key].append(value)
if not data:
raise SkipComponent("No Parsed Contents")
data['module_deps'] = list(data.get('depends', '').split(','))
data['module_name'] = data.get('filename', '').rsplit('/')[-1].split('.')[0]
return cls(data)
@property
def module_name(self):
"""
(str): This will return kernel module name when set, else empty str.
"""
return self.get('module_name', '')
@property
def module_path(self):
"""
(str): This will return kernel module path when set, else `None`.
"""
return self.get('filename', '')
@property
def module_deps(self):
"""
(list): This will return the list of kernel modules depend on the kernel
module when set, else `[]`.
"""
return self.get('module_deps', [])
@property
def module_firmware(self):
"""
(list): This will return the list of firmwares used by this module
when set, else `[]`.
"""
return self.get('firmware', [])
@property
def module_alias(self):
"""
(list): This will return the list of alias to this kernel module
when set, else `[]`.
"""
return self.get('alias', [])
@property
def module_parm(self):
"""
(list): This will return the list of parms for this kernel module
when set, else `[]`.
"""
return self.get('parm', [])
@property
def module_version(self):
"""
(str): This will return the kernel module version when set, else empty string.
"""
return self.get('version', '')
@property
def module_signer(self):
"""
(str): This will return the signer of kernel module when set, else empty string.
"""
return self.get('signer', '')
@property
def module_details(self):
"""
(dict): This will return the kernel module details when set.
"""
return self
[docs]@parser(Specs.modinfo_filtered_modules)
class KernelModulesInfo(CommandParser, dict):
"""
Class to parse the information about filtered kernel modules collected by
"modinfo filtered_modules". The result will be stored in a dictionary.
The key is the module name, the value is a instance of ModInfo with more
details.
Sample output::
filename: /lib/modules/3.10.0-957.10.1.el7.x86_64/kernel/drivers/net/vmxnet3/vmxnet3.ko.xz
version: 1.4.14.0-k
license: GPL v2
description: VMware vmxnet3 virtual NIC driver
author: VMware, Inc.
retpoline: Y
rhelversion: 7.6
srcversion: 7E672688ACACBDD2E363B63
alias: pci:v000015ADd000007B0sv*sd*bc*sc*i*
depends:
intree: Y
vermagic: 3.10.0-957.10.1.el7.x86_64 SMP mod_unload modversions
signer: Red Hat Enterprise Linux kernel signing key
sig_key: A5:70:18:DF:B6:C9:D6:1F:CF:CE:0A:3D:02:8B:B3:69:BD:76:CA:ED
sig_hashalgo: sha256
filename: /lib/modules/3.10.0-993.el7.x86_64/kernel/drivers/net/ethernet/intel/i40e/i40e.ko.xz
firmware: i40e/i40e-e2-7.13.1.0.fw
firmware: i40e/i40e-e1h-7.13.1.0.fw
version: 2.3.2-k
license: GPL
description: Intel(R) Ethernet Connection XL710 Network Driver
author: Intel Corporation, <e1000-devel@lists.sourceforge.net>
retpoline: Y
rhelversion: 7.7
srcversion: DC5C250666ADD8603966656
alias: pci:v00008086d0000158Bsv*sd*bc*sc*i*
alias: pci:v00008086d0000158Asv*sd*bc*sc*i*
depends: ptp
intree: Y
vermagic: 3.10.0-993.el7.x86_64 SMP mod_unload modversions
signer: Red Hat Enterprise Linux kernel signing key
sig_key: 81:7C:CB:07:72:4E:7F:B8:15:24:10:F9:27:2D:AA:CF:80:3E:CE:59
sig_hashalgo: sha256
parm: debug:Debug level (0=none,...,16=all), Debug mask (0x8XXXXXXX) (uint)
parm: int_mode: Force interrupt mode other than MSI-X (1 INT#x; 2 MSI) (int)
Raises:
SkipComponent: When nothing need to parse.
Examples:
>>> from insights.core.filters import add_filter
>>> from insights.specs import Specs
>>> add_filter(Specs.modinfo_modules, 'i40e')
>>> add_filter(Specs.modinfo_modules, 'vmxnet3')
>>> type(mods_info)
<class 'insights.parsers.modinfo.KernelModulesInfo'>
>>> 'i40e' in mods_info
True
>>> mods_info['i40e'].module_version
'2.3.2-k'
>>> mods_info['i40e'].module_path
'/lib/modules/3.10.0-993.el7.x86_64/kernel/drivers/net/ethernet/intel/i40e/i40e.ko.xz'
>>> sorted(mods_info['i40e'].module_firmware)
['i40e/i40e-e1h-7.13.1.0.fw', 'i40e/i40e-e2-7.13.1.0.fw']
>>> sorted(mods_info['i40e'].module_alias)
['pci:v00008086d0000158Asv*sd*bc*sc*i*', 'pci:v00008086d0000158Bsv*sd*bc*sc*i*']
>>> sorted(mods_info['i40e'].module_parm)
['debug:Debug level (0=none,...,16=all), Debug mask (0x8XXXXXXX) (uint)', 'int_mode: Force interrupt mode other than MSI-X (1 INT#x; 2 MSI) (int)']
>>> 'vmxnet3' in mods_info
True
Attributes:
retpoline_y (set): A set of names of the modules with the attribute "retpoline: Y".
retpoline_n (set): A set of names of the modules with the attribute "retpoline: N".
"""
[docs] def parse_content(self, content):
if (not content) or (not self.file_path):
raise SkipComponent("No Contents")
self.retpoline_y = set()
self.retpoline_n = set()
idx = None
for i, line in enumerate(content):
if line.startswith('filename:'):
if idx is not None:
m = ModInfo.from_content(content[idx:i])
name = m.module_name
self[name] = m
self.retpoline_y.add(name) if m.get('retpoline') == 'Y' else None
self.retpoline_n.add(name) if m.get('retpoline') == 'N' else None
idx = i
if idx is not None and idx < len(content):
m = ModInfo.from_content(content[idx:])
name = m.module_name
self[name] = m
self.retpoline_y.add(name) if m.get('retpoline') == 'Y' else None
self.retpoline_n.add(name) if m.get('retpoline') == 'N' else None
if len(self) == 0:
raise SkipComponent("No Parsed Contents")