Blame SOURCES/sos-bz1683904-option_to_limit_namespaces.patch

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