"""
ProcLimits - File ``/proc/<PID>/limits``
========================================
Parser for parsing the the ``limits`` file under special ``/proc/<PID>``
directory.
"""
from insights.core import LegacyItemAccess, Parser
from insights.core.exceptions import ParseException
from insights.core.plugins import parser
from insights.parsers import parse_fixed_table
from insights.specs import Specs
HEADER_SUBSTITUTE = [('Soft Limit', 'Soft_Limit'), ('Hard Limit', 'Hard_Limit')]
[docs]
class Limits(LegacyItemAccess):
"""
An object representing a line in the ``/proc/limits``. Each entry contains
below fixed attributes:
Attributes:
hard_limit(str): Hard limit
soft_limit(str): Soft limit
units(str): Unit of the limit value
"""
def __init__(self, data={}):
self.data = data
for k, v in data.items():
setattr(self, k, v)
[docs]
def items(self):
"""
To keep backward compatibility and let it can be iterated as a
dictionary.
"""
for k, v in self.data.items():
yield k, v
[docs]
class ProcLimits(Parser):
"""
Base class for parsing the ``limits`` file under special ``/proc/<PID>``
directory into a list of dictionaries by using the
:py:func:`insights.parsers.parse_fixed_table` function.
Each line is a dictionary of fields, named according to their definitions
in ``Limit``.
This class provides the '__len__' and '__iter__' methods to allow it to
be used as a list to iterate over the parsed dictionaries.
Each of the resource provided by this file will be set as an attribute.
The attribute name is the resource name got from the ``Limit`` column, which
is converted to lowercase and joined the words with underline '_'. If not
sure about whether an attribute is exist or not, check it via the
'__contains__' method before fetching it.
The attribute value is set to a :class:`Limits` which wraps the
corresponding ``hard_limit``, ``soft_limit`` and ``units``.
Typical content looks like::
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 10485760 unlimited bytes
Max core file size 0 unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 9 99 processes
Max open files 1024 4096 files
Max locked memory 65536 65536 bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 15211 15211 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 0 0
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us
Examples:
>>> len(proc_limits)
16
>>> proc_limits.max_processes.hard_limit
'99'
>>> proc_limits.max_processes.soft_limit
'9'
>>> 'max_cpu_time' in proc_limits
True
>>> proc_limits.max_cpu_time.soft_limit
'unlimited'
>>> proc_limits.max_cpu_time.units
'seconds'
Raises:
insights.core.exceptions.ParseException: if the ``limits`` file is empty or
doesn't exist.
"""
def __contains__(self, key):
return any(key == row['Limit'] for row in self.data)
def __len__(self):
return len(self.data)
def __iter__(self):
for row in self.data:
yield row
[docs]
def parse_content(self, content):
if len(content) == 0 or 'No such file or directory' in content[0]:
raise ParseException("Error: ", content[0] if content else 'empty file')
self.data = parse_fixed_table(content, header_substitute=HEADER_SUBSTITUTE)
for row in self.data:
row['Limit'] = row['Limit'].lower().replace(' ', '_')
setattr(self, row['Limit'],
Limits({'hard_limit': row['Hard_Limit'],
'soft_limit': row['Soft_Limit'],
'units': row['Units']}))
[docs]
@parser(Specs.httpd_limits)
class HttpdLimits(ProcLimits):
"""
Class for parsing the ``limits`` file of the ``httpd`` process.
"""
pass
[docs]
@parser(Specs.mysqld_limits)
class MysqldLimits(ProcLimits):
"""
Class for parsing the ``limits`` file of the ``mysqld`` process.
"""
pass
[docs]
@parser(Specs.ovs_vswitchd_limits)
class OvsVswitchdLimits(ProcLimits):
"""
Class for parsing the ``limits`` file of the ``ovs-vswitchd`` process.
"""
pass