diff options
author | Bryn M. Reeves <bmr@redhat.com> | 2019-02-21 12:48:27 +0000 |
---|---|---|
committer | Bryn M. Reeves <bmr@redhat.com> | 2019-03-22 17:44:13 +0000 |
commit | bd3498b72849815b422048614ee9e5e98f90b52c (patch) | |
tree | ff08cbec491575d98567d8e06e5c826708dde90c | |
parent | fc6721ac83c2626982f6c796f82b1386f123c66f (diff) | |
download | sos-bd3498b72849815b422048614ee9e5e98f90b52c.tar.gz |
[Plugin] add SoSPredicate implementation
Add a simple predicate class that can be used to gate collection
of certain data without adding conditional code into individual
plugins.
Signed-off-by: Bryn M. Reeves <bmr@redhat.com>
-rw-r--r-- | sos/plugins/__init__.py | 92 |
1 files changed, 86 insertions, 6 deletions
diff --git a/sos/plugins/__init__.py b/sos/plugins/__init__.py index c7dde774..3793edee 100644 --- a/sos/plugins/__init__.py +++ b/sos/plugins/__init__.py @@ -91,6 +91,81 @@ def _file_is_compressed(path): return path.endswith(('.gz', '.xz', '.bz', '.bz2')) +class SoSPredicate(object): + """A class to implement collection predicates. + + A predicate gates the collection of data by an sos plugin. For any + `add_cmd_output()`, `add_copy_spec()` or `add_journal()` call, the + passed predicate will be evaulated and collection will proceed if + the result is `True`, and not otherwise. + + Predicates may be used to control conditional data collection + without the need for explicit conditional blocks in plugins. + """ + #: The plugin that owns this predicate + _owner = None + + #: Skip all collection? + _dry_run = False + + #: Kernel module enablement list + _kmods = [] + + #: Services enablement list + _services = [] + + def __str(self, quote=False, prefix="", suffix=""): + """Return a string representation of this SoSPredicate with + optional prefix, suffix and value quoting. + """ + quotes = '"%s"' + pstr = "dry_run=%s, " % self._dry_run + + kmods = self._kmods + kmods = [quotes % k for k in kmods] if quote else kmods + pstr += "kmods=[%s], " % (",".join(kmods)) + + services = self._services + services = [quotes % s for s in services] if quote else services + pstr += "services=[%s]" % (",".join(services)) + + return prefix + pstr + suffix + + def __str__(self): + """Return a string representation of this SoSPredicate. + + "dry_run=False, kmods=[], services=[]" + """ + return self.__str() + + def __repr__(self): + """Return a machine readable string representation of this + SoSPredicate. + + "SoSPredicate(dry_run=False, kmods=[], services=[])" + """ + return self.__str(quote=True, prefix="SoSPredicate(", suffix=")") + + def __nonzero__(self): + """Predicate evaluation hook. + """ + pvalue = False + for k in self._kmods: + pvalue |= self._owner.is_module_loaded(k) + + for s in self._services: + pvalue |= self._owner.is_service(s) and self._owner.is_enabled(s) + + return pvalue and not self._dry_run + + def __init__(self, owner, dry_run=False, kmods=[], services=[]): + """Initialise a new SoSPredicate object. + """ + self._owner = owner + self._kmods = list(kmods) + self._services = list(services) + + class Plugin(object): """ This is the base class for sosreport plugins. Plugins should subclass this and set the class variables where applicable. @@ -741,7 +816,7 @@ class Plugin(object): def _add_cmd_output(self, cmd, suggest_filename=None, root_symlink=None, timeout=300, stderr=True, chroot=True, runat=None, env=None, binary=False, - sizelimit=None): + sizelimit=None, pred=None): """Internal helper to add a single command to the collection list.""" cmdt = ( cmd, suggest_filename, @@ -752,13 +827,17 @@ class Plugin(object): "'%s')") _logstr = "packed command tuple: " + _tuplefmt self._log_debug(_logstr % cmdt) - self.collect_cmds.append(cmdt) - self._log_info("added cmd output '%s'" % cmd) + if pred is None or pred: + self.collect_cmds.append(cmdt) + self._log_info("added cmd output '%s'" % cmd) + else: + self._log_info("skipped cmd output '%s' due to predicate (%s)" % + (cmd, pred)) def add_cmd_output(self, cmds, suggest_filename=None, root_symlink=None, timeout=300, stderr=True, chroot=True, runat=None, env=None, binary=False, - sizelimit=None): + sizelimit=None, pred=None): """Run a program or a list of programs and collect the output""" if isinstance(cmds, six.string_types): cmds = [cmds] @@ -770,7 +849,8 @@ class Plugin(object): self._add_cmd_output(cmd, suggest_filename=suggest_filename, root_symlink=root_symlink, timeout=timeout, stderr=stderr, chroot=chroot, runat=runat, - env=env, binary=binary, sizelimit=sizelimit) + env=env, binary=binary, sizelimit=sizelimit, + pred=pred) def get_cmd_output_path(self, name=None, make=True): """Return a path into which this module should store collected @@ -860,7 +940,7 @@ class Plugin(object): def is_module_loaded(self, module_name): """Return whether specified moudle as module_name is loaded or not""" if len(grep("^" + module_name + " ", "/proc/modules")) == 0: - return None + return False else: return True |