Mini Shell
"""
Module for running ethtool command
.. versionadded:: 2016.3.0
:codeauthor: Krzysztof Pawlowski <msciciel@msciciel.eu>
:maturity: new
:depends: python-ethtool
:platform: linux
"""
import logging
import os
import salt.utils.path
from salt.exceptions import CommandExecutionError
try:
import ethtool
HAS_ETHTOOL = True
except ImportError:
HAS_ETHTOOL = False
log = logging.getLogger(__name__)
ethtool_coalesce_map = {
"pkt_rate_high": "pkt_rate_high",
"pkt_rate_low": "pkt_rate_low",
"sample_interval": "rate_sample_interval",
"rx_usecs": "rx_coalesce_usecs",
"rx_usecs_high": "rx_coalesce_usecs_high",
"rx_usecs_irq": "rx_coalesce_usecs_irq",
"rx_usecs_low": "rx_coalesce_usecs_low",
"rx_frames": "rx_max_coalesced_frames",
"rx_frames_high": "rx_max_coalesced_frames_high",
"rx_frames_irg": "rx_max_coalesced_frames_irq",
"rx_frames_low": "rx_max_coalesced_frames_low",
"stats_block_usecs": "stats_block_coalesce_usecs",
"tx_usecs": "tx_coalesce_usecs",
"tx_usecs_high": "tx_coalesce_usecs_high",
"tx_usecs_irq": "tx_coalesce_usecs_irq",
"tx_usecs_low": "tx_coalesce_usecs_low",
"tx_frames": "tx_max_coalesced_frames",
"tx_frames_high": "tx_max_coalesced_frames_high",
"tx_frames_irq": "tx_max_coalesced_frames_irq",
"tx_frames_low": "tx_max_coalesced_frames_low",
"adaptive_rx": "use_adaptive_rx_coalesce",
"adaptive_tx": "use_adaptive_tx_coalesce",
}
ethtool_coalesce_remap = {}
for k, v in ethtool_coalesce_map.items():
ethtool_coalesce_remap[v] = k
ethtool_ring_map = {
"rx": "rx_pending",
"rx_max": "rx_max_pending",
"rx_mini": "rx_mini_pending",
"rx_mini_max": "rx_mini_max_pending",
"rx_jumbo": "rx_jumbo_pending",
"rx_jumbo_max": "rx_jumbo_max_pending",
"tx": "tx_pending",
"tx_max": "tx_max_pending",
}
ethtool_ring_remap = {}
for k, v in ethtool_ring_map.items():
ethtool_ring_remap[v] = k
# Define the module's virtual name
__virtualname__ = "ethtool"
def __virtual__():
"""
Only load this module if python-ethtool is installed
"""
if HAS_ETHTOOL:
return __virtualname__
else:
return (
False,
"The ethtool module could not be loaded: ethtool "
"python libraries not found.",
)
def show_ring(devname):
"""
Queries the specified network device for rx/tx ring parameter information
CLI Example:
.. code-block:: bash
salt '*' ethtool.show_ring <devname>
"""
try:
ring = ethtool.get_ringparam(devname)
except OSError:
log.error("Ring parameters not supported on %s", devname)
return "Not supported"
ret = {}
for key, value in ring.items():
ret[ethtool_ring_remap[key]] = ring[key]
return ret
def show_coalesce(devname):
"""
Queries the specified network device for coalescing information
CLI Example:
.. code-block:: bash
salt '*' ethtool.show_coalesce <devname>
"""
try:
coalesce = ethtool.get_coalesce(devname)
except OSError:
log.error("Interrupt coalescing not supported on %s", devname)
return "Not supported"
ret = {}
for key, value in coalesce.items():
ret[ethtool_coalesce_remap[key]] = coalesce[key]
return ret
def show_driver(devname):
"""
Queries the specified network device for associated driver information
CLI Example:
.. code-block:: bash
salt '*' ethtool.show_driver <devname>
"""
try:
module = ethtool.get_module(devname)
except OSError:
log.error("Driver information not implemented on %s", devname)
return "Not implemented"
try:
businfo = ethtool.get_businfo(devname)
except OSError:
log.error("Bus information no available on %s", devname)
return "Not available"
ret = {
"driver": module,
"bus_info": businfo,
}
return ret
def set_ring(devname, **kwargs):
"""
Changes the rx/tx ring parameters of the specified network device
CLI Example:
.. code-block:: bash
salt '*' ethtool.set_ring <devname> [rx=N] [rx_mini=N] [rx_jumbo=N] [tx=N]
"""
try:
ring = ethtool.get_ringparam(devname)
except OSError:
log.error("Ring parameters not supported on %s", devname)
return "Not supported"
changed = False
for param, value in kwargs.items():
if param in ethtool_ring_map:
param = ethtool_ring_map[param]
if param in ring:
if ring[param] != value:
ring[param] = value
changed = True
try:
if changed:
ethtool.set_ringparam(devname, ring)
return show_ring(devname)
except OSError:
log.error("Invalid ring arguments on %s: %s", devname, ring)
return "Invalid arguments"
def set_coalesce(devname, **kwargs):
"""
Changes the coalescing settings of the specified network device
CLI Example:
.. code-block:: bash
salt '*' ethtool.set_coalesce <devname> [adaptive_rx=on|off] [adaptive_tx=on|off] [rx_usecs=N] [rx_frames=N]
[rx_usecs_irq=N] [rx_frames_irq=N] [tx_usecs=N] [tx_frames=N] [tx_usecs_irq=N] [tx_frames_irq=N]
[stats_block_usecs=N] [pkt_rate_low=N] [rx_usecs_low=N] [rx_frames_low=N] [tx_usecs_low=N] [tx_frames_low=N]
[pkt_rate_high=N] [rx_usecs_high=N] [rx_frames_high=N] [tx_usecs_high=N] [tx_frames_high=N]
[sample_interval=N]
"""
try:
coalesce = ethtool.get_coalesce(devname)
except OSError:
log.error("Interrupt coalescing not supported on %s", devname)
return "Not supported"
changed = False
for param, value in kwargs.items():
if param in ethtool_coalesce_map:
param = ethtool_coalesce_map[param]
if param in coalesce:
if coalesce[param] != value:
coalesce[param] = value
changed = True
try:
if changed:
# pylint: disable=too-many-function-args
ethtool.set_coalesce(devname, coalesce)
# pylint: enable=too-many-function-args
return show_coalesce(devname)
except OSError:
log.error("Invalid coalesce arguments on %s: %s", devname, coalesce)
return "Invalid arguments"
def show_offload(devname):
"""
Queries the specified network device for the state of protocol offload and other features
CLI Example:
.. code-block:: bash
salt '*' ethtool.show_offload <devname>
"""
try:
sg = ethtool.get_sg(devname) and "on" or "off"
except OSError:
sg = "not supported"
try:
tso = ethtool.get_tso(devname) and "on" or "off"
except OSError:
tso = "not supported"
try:
ufo = ethtool.get_ufo(devname) and "on" or "off"
except OSError:
ufo = "not supported"
try:
gso = ethtool.get_gso(devname) and "on" or "off"
except OSError:
gso = "not supported"
offload = {
"scatter_gather": sg,
"tcp_segmentation_offload": tso,
"udp_fragmentation_offload": ufo,
"generic_segmentation_offload": gso,
}
return offload
def set_offload(devname, **kwargs):
"""
Changes the offload parameters and other features of the specified network device
CLI Example:
.. code-block:: bash
salt '*' ethtool.set_offload <devname> tcp_segmentation_offload=on
"""
for param, value in kwargs.items():
if param == "tcp_segmentation_offload":
value = value == "on" and 1 or 0
try:
ethtool.set_tso(devname, value)
except OSError:
return "Not supported"
return show_offload(devname)
def _ethtool_command(devname, *args, **kwargs):
"""
Helper function to build an ethtool command
"""
ethtool = salt.utils.path.which("ethtool")
if not ethtool:
raise CommandExecutionError("Command 'ethtool' cannot be found")
switches = " ".join(arg for arg in args)
params = " ".join(f"{key} {val}" for key, val in kwargs.items())
cmd = f"{ethtool} {switches} {devname} {params}".strip()
ret = __salt__["cmd.run"](cmd, ignore_retcode=True).splitlines()
if ret and ret[0].startswith("Cannot"):
raise CommandExecutionError(ret[0])
return ret
def _validate_params(valid_params, kwargs):
"""
Helper function to validate parameters to ethtool commands. Boolean values
will be transformed into ``on`` and ``off`` to match expected syntax.
"""
validated = {}
for key, val in kwargs.items():
key = key.lower()
if key in valid_params:
if val is True:
val = "on"
elif val is False:
val = "off"
validated[key] = val
if not validated:
raise CommandExecutionError(
f"None of the valid parameters were provided: {valid_params}"
)
return validated
def show_pause(devname):
"""
.. versionadded:: 3006.0
Queries the specified network device for associated pause information
CLI Example:
.. code-block:: bash
salt '*' ethtool.show_pause <devname>
"""
data = {}
content = _ethtool_command(devname, "-a")
for line in content[1:]:
if line.strip():
(key, value) = (s.strip() for s in line.split(":", 1))
data[key] = value == "on"
return data
def set_pause(devname, **kwargs):
"""
.. versionadded:: 3006.0
Changes the pause parameters of the specified network device
CLI Example:
.. code-block:: bash
salt '*' ethtool.set_pause <devname> autoneg=off rx=off tx=off
"""
valid_params = ["autoneg", "rx", "tx"]
params = _validate_params(valid_params, kwargs)
ret = _ethtool_command(devname, "-A", **params)
if not ret:
return True
return ret
def show_features(devname):
"""
.. versionadded:: 3006.0
Queries the specified network device for associated feature information
CLI Example:
.. code-block:: bash
salt '*' ethtool.show_features <devname>
"""
data = {}
content = _ethtool_command(devname, "-k")
for line in content[1:]:
if ":" in line:
key, value = (s.strip() for s in line.strip().split(":", 1))
fixed = "fixed" in value
if fixed:
value = value.split()[0].strip()
data[key.strip()] = {"on": value == "on", "fixed": fixed}
return data
def set_feature(devname, **kwargs):
"""
.. versionadded:: 3006.0
Changes the feature parameters of the specified network device
CLI Example:
.. code-block:: bash
salt '*' ethtool.set_feature <devname> sg=off
"""
valid_params = [
"rx",
"tx",
"sg",
"tso",
"ufo",
"gso",
"gro",
"lro",
"rxvlan",
"txvlan",
"ntuple",
"rxhash",
]
params = _validate_params(valid_params, kwargs)
ret = _ethtool_command(devname, "-K", **params)
if not ret:
return True
return os.linesep.join(ret)
Zerion Mini Shell 1.0