From c20bd8d489c45401db55cf89bf7d4d0f7623a4fe Mon Sep 17 00:00:00 2001
From: Jan Jansky <jjansky@redhat.com>
Date: Thu, 6 Feb 2020 08:56:11 +0100
Subject: [PATCH] [networking] options to limit namespaces
* Added posibility to define namespaces with
parameter namespaces = "". Posible regexp
like "eth* ens4".
* Added inspect_namespaces which defines how
many namespaces should be inspected, by
default unlimited
* Added ethtool_namespaces variable which
is by default true and if set to false it
will not execute ethtool commands for
namespaces
* Changed options for OpenStack environment
where ethtool_namespaces=False and
inspect_namespaces = 200
Closes: #1916
Signed-off-by: Jan Jansky <jjansky@redhat.com>
Signed-off-by: Pavel Moravec <pmoravec@redhat.com>
---
--- a/sos/plugins/networking.py
+++ b/sos/plugins/networking.py
@@ -8,7 +8,7 @@
from sos.plugins import Plugin, RedHatPlugin, UbuntuPlugin, DebianPlugin
from os import listdir
-import re
+from re import match
class Networking(Plugin):
@@ -17,10 +17,17 @@
plugin_name = "networking"
profiles = ('network', 'hardware', 'system')
trace_host = "www.example.com"
- option_list = [(
+ option_list = [
("traceroute", "collect a traceroute to %s" % trace_host, "slow",
- False)
- )]
+ False),
+ ("namespace_pattern", "Specific namespaces pattern to be " +
+ "collected, namespaces pattern should be separated by whitespace " +
+ "as for example \"eth* ens2\"", "fast", ""),
+ ("namespaces", "Number of namespaces to collect, 0 for unlimited. " +
+ "Incompatible with the namespace_pattern plugin option", "slow", 0),
+ ("ethtool_namespaces", "Define if ethtool commands should be " +
+ "collected for namespaces", "slow", True)
+ ]
# switch to enable netstat "wide" (non-truncated) output mode
ns_wide = "-W"
@@ -196,8 +203,41 @@
# per-namespace.
ip_netns_file = self.get_cmd_output_now("ip netns")
cmd_prefix = "ip netns exec "
+ # Regex initialization outside of for loop
if ip_netns_file:
- for namespace in self.get_ip_netns(ip_netns_file):
+ if self.get_option("namespace_pattern"):
+ pattern = '(?:%s$)' % '$|'.join(
+ self.get_option("namespace_pattern").split()
+ ).replace('*', '.*')
+ out_ns = []
+ with open(ip_netns_file, 'r') as file:
+ ip_netns = file.read()
+ for line in ip_netns.splitlines():
+ # If there's no namespaces, no need to continue
+ if line.startswith("Object \"netns\" is unknown") \
+ or line.isspace() \
+ or line[:1].isspace():
+ continue
+
+ # if namespace_pattern defined, append only namespaces
+ # matching with pattern
+ if self.get_option("namespace_pattern"):
+ if bool(match(pattern, line)):
+ out_ns.append(line.partition(' ')[0])
+
+ # if namespaces is defined and namespace_pattern is not defined
+ # remove from out_ns namespaces with higher index than defined
+ elif self.get_option("namespaces") != 0:
+ out_ns.append(line.partition(' ')[0])
+ if len(out_ns) == self.get_option("namespaces"):
+ self._log_warn("Limiting namespace iteration " +
+ "to first %s namespaces found"
+ % self.get_option("namespaces"))
+ break
+ else:
+ out_ns.append(line.partition(' ')[0])
+
+ for namespace in out_ns:
ns_cmd_prefix = cmd_prefix + namespace + " "
self.add_cmd_output([
ns_cmd_prefix + "ip address show",
@@ -208,25 +248,27 @@
ns_cmd_prefix + "netstat -s",
ns_cmd_prefix + "netstat %s -agn" % self.ns_wide
])
-
- # Devices that exist in a namespace use less ethtool
- # parameters. Run this per namespace.
- for namespace in self.get_ip_netns(ip_netns_file):
- ns_cmd_prefix = cmd_prefix + namespace + " "
- netns_netdev_list = self.call_ext_prog(ns_cmd_prefix +
+ # Collect ethtool commands only when ethtool_namespaces
+ # is set to true.
+ if self.get_option("ethtool_namespaces"):
+ # Devices that exist in a namespace use less ethtool
+ # parameters. Run this per namespace.
+ for namespace in out_ns:
+ ns_cmd_prefix = cmd_prefix + namespace + " "
+ netns_netdev_list = self.call_ext_prog(ns_cmd_prefix +
"ls -1 /sys/class/net/")
- for eth in netns_netdev_list['output'].splitlines():
- # skip 'bonding_masters' file created when loading the
- # bonding module but the file does not correspond to
- # a device
- if eth == "bonding_masters":
- continue
- self.add_cmd_output([
- ns_cmd_prefix + "ethtool " + eth,
- ns_cmd_prefix + "ethtool -i " + eth,
- ns_cmd_prefix + "ethtool -k " + eth,
- ns_cmd_prefix + "ethtool -S " + eth
- ])
+ for eth in netns_netdev_list['output'].splitlines():
+ # skip 'bonding_masters' file created when loading the
+ # bonding module but the file does not correspond to
+ # a device
+ if eth == "bonding_masters":
+ continue
+ self.add_cmd_output([
+ ns_cmd_prefix + "ethtool " + eth,
+ ns_cmd_prefix + "ethtool -i " + eth,
+ ns_cmd_prefix + "ethtool -k " + eth,
+ ns_cmd_prefix + "ethtool -S " + eth
+ ])
return
--- a/sos/policies/redhat.py
+++ b/sos/policies/redhat.py
@@ -192,8 +192,6 @@
_opts_verify = SoSOptions(verify=True)
_opts_all_logs = SoSOptions(all_logs=True)
_opts_all_logs_verify = SoSOptions(all_logs=True, verify=True)
-_opts_all_logs_no_lsof = SoSOptions(all_logs=True,
- plugopts=['process.lsof=off'])
_cb_plugs = ['abrt', 'block', 'boot', 'dnf', 'dracut', 'filesys', 'grub2',
'hardware', 'host', 'kernel', 'logs', 'lvm2', 'memory', 'rpm',
'process', 'systemd', 'yum', 'xfs']
@@ -208,6 +206,10 @@
RHOSP = "rhosp"
RHOSP_DESC = "Red Hat OpenStack Platform"
+RHOSP_OPTS = SoSOptions(plugopts=[
+ 'process.lsof=off',
+ 'networking.ethtool_namespaces=False',
+ 'networking.namespaces=200'])
RHOCP = "ocp"
RHOCP_DESC = "OpenShift Container Platform by Red Hat"
@@ -221,7 +223,6 @@
CB_OPTS = SoSOptions(verify=True, all_logs=True, onlyplugins=_cb_plugs)
CB_NOTE = ("Data collection will be limited to a boot-affecting scope")
-NOTE_SIZE = "This preset may increase report size"
NOTE_TIME = "This preset may increase report run time"
NOTE_SIZE_TIME = "This preset may increase report size and run time"
@@ -229,8 +230,7 @@
RHV: PresetDefaults(name=RHV, desc=RHV_DESC, note=NOTE_TIME,
opts=_opts_verify),
RHEL: PresetDefaults(name=RHEL, desc=RHEL_DESC),
- RHOSP: PresetDefaults(name=RHOSP, desc=RHOSP_DESC, note=NOTE_SIZE,
- opts=_opts_all_logs_no_lsof),
+ RHOSP: PresetDefaults(name=RHOSP, desc=RHOSP_DESC, opts=RHOSP_OPTS),
RHOCP: PresetDefaults(name=RHOCP, desc=RHOCP_DESC, note=NOTE_SIZE_TIME,
opts=_opts_all_logs_verify),
RH_SATELLITE: PresetDefaults(name=RH_SATELLITE, desc=RH_SATELLITE_DESC,