aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--man/en/sos-report.110
-rw-r--r--sos/collector/__init__.py4
-rw-r--r--sos/report/__init__.py4
-rw-r--r--sos/report/plugins/__init__.py24
-rw-r--r--sos/report/plugins/networking.py2
-rw-r--r--tests/unittests/plugin_tests.py2
6 files changed, 35 insertions, 11 deletions
diff --git a/man/en/sos-report.1 b/man/en/sos-report.1
index f6bd6c6a..36b337df 100644
--- a/man/en/sos-report.1
+++ b/man/en/sos-report.1
@@ -18,6 +18,7 @@ sos report \- Collect and package diagnostic and support data
[--threads threads]\fR
[--plugin-timeout TIMEOUT]\fR
[--cmd-timeout TIMEOUT]\fR
+ [--namespaces NAMESPACES]\fR
[-s|--sysroot SYSROOT]\fR
[-c|--chroot {auto|always|never}\fR
[--tmp-dir directory]\fR
@@ -289,6 +290,15 @@ Note that setting --cmd-timeout (or -k logs.cmd-timeout) high should be followed
by increasing the --plugin-timeout equivalent, otherwise the plugin can easily
timeout on slow commands execution.
.TP
+.B \--namespaces NAMESPACES
+For plugins that iterate collections over namespaces that exist on the system,
+for example the networking plugin collecting `ip` command output for each network
+namespace, use this option to limit the number of namespaces that will be collected.
+
+Use '0' (default) for no limit - all namespaces will be used for collections.
+
+Note that specific plugins may provide a similar `namespaces` plugin option. If
+the plugin option is used, it will override this option.
.B \--case-id NUMBER
Specify a case identifier to associate with the archive.
Identifiers may include alphanumeric characters, commas and periods ('.').
diff --git a/sos/collector/__init__.py b/sos/collector/__init__.py
index f072287e..57ef074e 100644
--- a/sos/collector/__init__.py
+++ b/sos/collector/__init__.py
@@ -74,6 +74,7 @@ class SoSCollector(SoSComponent):
'map_file': '/etc/sos/cleaner/default_mapping',
'master': '',
'primary': '',
+ 'namespaces': None,
'nodes': [],
'no_env_vars': False,
'no_local': False,
@@ -281,6 +282,9 @@ class SoSCollector(SoSComponent):
sos_grp.add_argument('-o', '--only-plugins', action="extend",
default=[],
help='Run these plugins only')
+ sos_grp.add_argument('--namespaces', default=None,
+ help='limit number of namespaces to collect '
+ 'output for - 0 means unlimited')
sos_grp.add_argument('--no-env-vars', action='store_true',
default=False,
help='Do not collect env vars in sosreports')
diff --git a/sos/report/__init__.py b/sos/report/__init__.py
index 411c4eb0..4e9e5fcb 100644
--- a/sos/report/__init__.py
+++ b/sos/report/__init__.py
@@ -100,6 +100,7 @@ class SoSReport(SoSComponent):
'skip_commands': [],
'skip_files': [],
'skip_plugins': [],
+ 'namespaces': None,
'no_report': False,
'no_env_vars': False,
'no_postproc': False,
@@ -250,6 +251,9 @@ class SoSReport(SoSComponent):
type=int, default=25,
help="limit the size of collected logs "
"(in MiB)")
+ report_grp.add_argument("--namespaces", default=None,
+ help="limit number of namespaces to collect "
+ "output for - 0 means unlimited")
report_grp.add_argument("-n", "--skip-plugins", action="extend",
dest="skip_plugins", type=str,
help="disable these plugins", default=[])
diff --git a/sos/report/plugins/__init__.py b/sos/report/plugins/__init__.py
index 1bc7b6fe..d851ef3e 100644
--- a/sos/report/plugins/__init__.py
+++ b/sos/report/plugins/__init__.py
@@ -1272,6 +1272,11 @@ class Plugin(object):
val = parms['enabled']
if val is not None:
return val
+ else:
+ # if the value is `None`, use any non-zero default here,
+ # but still return `None` if no default is given since
+ # optionname did exist and had a `None` value
+ return default or val
return default
@@ -2849,11 +2854,13 @@ class Plugin(object):
continue
return pids
- def get_network_namespaces(self, ns_pattern=None, ns_max=0):
+ def get_network_namespaces(self, ns_pattern=None, ns_max=None):
+ if ns_max is None and self.commons['cmdlineopts'].namespaces:
+ ns_max = self.commons['cmdlineopts'].namespaces
return self.filter_namespaces(self.commons['namespaces']['network'],
ns_pattern, ns_max)
- def filter_namespaces(self, ns_list, ns_pattern=None, ns_max=0):
+ def filter_namespaces(self, ns_list, ns_pattern=None, ns_max=None):
"""Filter a list of namespaces by regex pattern or max number of
namespaces (options originally present in the networking plugin.)
"""
@@ -2865,15 +2872,14 @@ class Plugin(object):
'(?:%s$)' % '$|'.join(ns_pattern.split()).replace('*', '.*')
)
for ns in ns_list:
- # if ns_pattern defined, append only namespaces
- # matching with pattern
+ # if ns_pattern defined, skip namespaces not matching the pattern
if ns_pattern:
- if bool(re.match(pattern, ns)):
- out_ns.append(ns)
+ if not bool(re.match(pattern, ns)):
+ continue
- # if ns_max is defined and ns_pattern is not defined
- # remove from out_ns namespaces with higher index than defined
- elif ns_max != 0:
+ # if ns_max is defined at all, limit returned list to that number
+ # this allows the use of both '0' and `None` to mean unlimited
+ elif ns_max:
out_ns.append(ns)
if len(out_ns) == ns_max:
self._log_warn("Limiting namespace iteration "
diff --git a/sos/report/plugins/networking.py b/sos/report/plugins/networking.py
index 632e3cfe..ae6cf0a1 100644
--- a/sos/report/plugins/networking.py
+++ b/sos/report/plugins/networking.py
@@ -24,7 +24,7 @@ class Networking(Plugin):
"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),
+ "Incompatible with the namespace_pattern option", "slow", None),
("ethtool_namespaces", "Define if ethtool commands should be " +
"collected for namespaces", "slow", True),
("eepromdump", "collect 'ethtool -e' for all devices", "slow", False)
diff --git a/tests/unittests/plugin_tests.py b/tests/unittests/plugin_tests.py
index 1d6ce73a..8dc038cb 100644
--- a/tests/unittests/plugin_tests.py
+++ b/tests/unittests/plugin_tests.py
@@ -244,7 +244,7 @@ class PluginTests(unittest.TestCase):
'cmdlineopts': MockOptions(),
'devices': {}
})
- self.assertEquals(p.get_option("opt"), 0)
+ self.assertEquals(p.get_option("opt"), None)
def test_get_unset_plugin_option_with_default(self):
# this shows that even when we pass in a default to get,