Blame SOURCES/sos-bz1683904-option_to_limit_namespaces.patch

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