From 82e4ee224706b5eb377b35f88c852dd79c7cb25d Mon Sep 17 00:00:00 2001 From: "Bryn M. Reeves" Date: Wed, 30 Aug 2017 13:31:56 +0100 Subject: [sosreport] add per-plugin package verification lists Add a new mechanism for plugins to declare a per-plugin list of packages to verify when the global --verify option is enabled. Historically this was implemented in the package manager plugin for each distribution (e.g. rpm.py for Red Hat distros and dpkg.py for the Debian family). This gives limited granularity and blocks the ability to verify only a subset of packages, or to only verify packages for a certain set of plugins. This change adds a new optional member to Plugin: verify_packages which when set will generate an additional command to be run by that plugin. The plugin calls into the PackageManager via the policy class to determine the correct package manager command to run. A plugin can request optional package verification by declaring a new 'verify_packages' member (or building one during setup()): plugin_name = 'foo' packages = ('foo', 'bar', 'baz', 'qux') verify_packages = ('foo', 'bar') Verification is only performed if the --verify switch is used. Signed-off-by: Bryn M. Reeves --- sos/plugins/__init__.py | 8 ++++++++ sos/policies/__init__.py | 44 +++++++++++++++++++++++++++++++++++++++++--- sos/policies/redhat.py | 9 ++++++++- sos/sosreport.py | 2 ++ 4 files changed, 59 insertions(+), 4 deletions(-) diff --git a/sos/plugins/__init__.py b/sos/plugins/__init__.py index 28c6f197..995989b9 100644 --- a/sos/plugins/__init__.py +++ b/sos/plugins/__init__.py @@ -955,6 +955,14 @@ class Plugin(object): """ self.add_copy_spec(list(self.files)) + def setup_verify(self): + if not hasattr(self, "verify_packages") or not self.verify_packages: + return + pm = self.policy().package_manager + verify_cmd = pm.build_verify_command(self.verify_packages) + if verify_cmd: + self.add_cmd_output(verify_cmd) + def postproc(self): """Perform any postprocessing. To be replaced by a plugin if required. """ diff --git a/sos/policies/__init__.py b/sos/policies/__init__.py index 52afc823..087cf6a7 100644 --- a/sos/policies/__init__.py +++ b/sos/policies/__init__.py @@ -55,12 +55,18 @@ class PackageManager(object): """ query_command = None + verify_command = None + verify_filter = None chroot = None - def __init__(self, query_command=None, chroot=None): + def __init__(self, chroot=None, query_command=None, + verify_command=None, verify_filter=None): self.packages = {} - if query_command: - self.query_command = query_command + + self.query_command = query_command if query_command else None + self.verify_command = verify_command if verify_command else None + self.verify_filter = verify_filter if verify_filter else None + if chroot: self.chroot = chroot @@ -126,6 +132,38 @@ class PackageManager(object): name = "-".join(fields[:-3]) return (name, version, release, arch) + def build_verify_command(self, packages): + """build_verify_command(self, packages) -> str + Generate a command to verify the list of packages given + in ``packages`` using the native package manager's + verification tool. + + The command to be executed is returned as a string that + may be passed to a command execution routine (for e.g. + ``sos_get_command_output()``. + + :param packages: a string, or a list of strings giving + package names to be verified. + :returns: a string containing an executable command + that will perform verification of the given + packages. + :returntype: str or ``NoneType`` + """ + if not self.verify_command: + return None + + by_regex = self.all_pkgs_by_name_regex + verify_list = map(by_regex, packages) + verify_packages = "" + for package_list in verify_list: + for package in package_list: + if any([f in package for f in self.verify_filter]): + continue + if len(verify_packages): + verify_packages += " " + verify_packages += package + return self.verify_command + " " + verify_packages + class Policy(object): diff --git a/sos/policies/redhat.py b/sos/policies/redhat.py index ec1d9748..c7449439 100644 --- a/sos/policies/redhat.py +++ b/sos/policies/redhat.py @@ -40,6 +40,8 @@ class RedHatPolicy(LinuxPolicy): _redhat_release = '/etc/redhat-release' _tmp_dir = "/var/tmp" _rpmq_cmd = 'rpm -qa --queryformat "%{NAME}|%{VERSION}\\n"' + _rpmv_cmd = 'rpm -V' + _rpmv_filter = ["debuginfo", "-devel"] _in_container = False _host_sysroot = '/' @@ -53,7 +55,12 @@ class RedHatPolicy(LinuxPolicy): self._host_sysroot = sysroot else: sysroot = self._container_init() - self.package_manager = PackageManager(self._rpmq_cmd, chroot=sysroot) + + self.package_manager = PackageManager(query_command=self._rpmq_cmd, + verify_command=self._rpmv_cmd, + verify_filter=self._rpmv_filter, + chroot=sysroot) + self.valid_subclasses = [RedHatPlugin] pkgs = self.package_manager.all_pkgs() diff --git a/sos/sosreport.py b/sos/sosreport.py index de3bca8f..75c5bd66 100644 --- a/sos/sosreport.py +++ b/sos/sosreport.py @@ -1250,6 +1250,8 @@ class SoSReport(object): try: plug.archive = self.archive plug.setup() + if self.opts.verify: + plug.setup_verify() except KeyboardInterrupt: raise except (OSError, IOError) as e: -- cgit