%PDF- %PDF-
Direktori : /usr/lib/python3/dist-packages/sos/policies/package_managers/ |
Current File : //usr/lib/python3/dist-packages/sos/policies/package_managers/__init__.py |
# Copyright 2020 Red Hat, Inc. Jake Hunsaker <jhunsake@redhat.com> # This file is part of the sos project: https://github.com/sosreport/sos # # This copyrighted material is made available to anyone wishing to use, # modify, copy, or redistribute it subject to the terms and conditions of # version 2 of the GNU General Public License. # # See the LICENSE file in the source distribution for further information. import re import fnmatch from sos.utilities import shell_out from pipes import quote class PackageManager(): """Encapsulates a package manager. If you provide a query_command to the constructor it should print each package on the system in the following format:: package name|package.version You may also subclass this class and provide a _generate_pkg_list method to build the list of packages and versions. :cvar query_command: The command to use for querying packages :vartype query_command: ``str`` or ``None`` :cvar verify_command: The command to use for verifying packages :vartype verify_command: ``str`` or ``None`` :cvar verify_filter: Optional filter to use for controlling package verification :vartype verify_filter: ``str or ``None`` :cvar files_command: The command to use for getting file lists for packages :vartype files_command: ``str`` or ``None`` :cvar chroot: Perform a chroot when executing `files_command` :vartype chroot: ``bool`` :cvar remote_exec: If package manager is on a remote system (e.g. for sos collect), prepend this SSH command to run remotely :vartype remote_exec: ``str`` or ``None`` """ query_command = None verify_command = None verify_filter = None files_command = None chroot = None files = None def __init__(self, chroot=None, query_command=None, verify_command=None, verify_filter=None, files_command=None, remote_exec=None): self._packages = {} self.files = [] self.query_command = query_command or self.query_command self.verify_command = verify_command or self.verify_command self.verify_filter = verify_filter or self.verify_filter self.files_command = files_command or self.files_command # if needed, append the remote command to these so that this returns # the remote package details, not local if remote_exec: for cmd in ['query_command', 'verify_command', 'files_command']: if getattr(self, cmd) is not None: _cmd = getattr(self, cmd) setattr(self, cmd, "%s %s" % (remote_exec, quote(_cmd))) if chroot: self.chroot = chroot @property def packages(self): if not self._packages: self._generate_pkg_list() return self._packages def all_pkgs_by_name(self, name): """ Get a list of packages that match name. :param name: The name of the package :type name: ``str`` :returns: List of all packages matching `name` :rtype: ``list`` """ return fnmatch.filter(self.packages.keys(), name) def all_pkgs_by_name_regex(self, regex_name, flags=0): """ Get a list of packages that match regex_name. :param regex_name: The regex to use for matching package names against :type regex_name: ``str`` :param flags: Flags for the `re` module when matching `regex_name` :returns: All packages matching `regex_name` :rtype: ``list`` """ reg = re.compile(regex_name, flags) return [pkg for pkg in self.packages.keys() if reg.match(pkg)] def pkg_by_name(self, name): """ Get a single package that matches name. :param name: The name of the package :type name: ``str`` :returns: The first package that matches `name` :rtype: ``str`` """ try: return self.packages[name] except Exception: return None def _generate_pkg_list(self): """Generates a dictionary of packages for internal use by the package manager in the format:: {'package_name': {'name': 'package_name', 'version': 'major.minor.version'}} """ if self.query_command: cmd = self.query_command pkg_list = shell_out( cmd, timeout=0, chroot=self.chroot ).splitlines() for pkg in pkg_list: if '|' not in pkg: continue elif pkg.count("|") == 1: name, version = pkg.split("|") release = None elif pkg.count("|") == 2: name, version, release = pkg.split("|") self._packages[name] = { 'name': name, 'version': version.split(".") } release = release if release else None self._packages[name]['release'] = release def pkg_version(self, pkg): """Returns the entry in self.packages for pkg if it exists :param pkg: The name of the package :type pkg: ``str`` :returns: Package name and version, if package exists :rtype: ``dict`` if found, else ``None`` """ if pkg in self.packages: return self.packages[pkg] return None def pkg_nvra(self, pkg): """Get the name, version, release, and architecture for a package :param pkg: The name of the package :type pkg: ``str`` :returns: name, version, release, and arch of the package :rtype: ``tuple`` """ fields = pkg.split("-") version, release, arch = fields[-3:] name = "-".join(fields[:-3]) return (name, version, release, arch) def all_files(self): """ Get a list of files known by the package manager :returns: All files known by the package manager :rtype: ``list`` """ if self.files_command and not self.files: cmd = self.files_command files = shell_out(cmd, timeout=0, chroot=self.chroot) self.files = files.splitlines() return self.files 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. :rtype: str or ``NoneType`` """ if not self.verify_command: return None # The re.match(pkg) used by all_pkgs_by_name_regex() may return # an empty list (`[[]]`) when no package matches: avoid building # an rpm -V command line with the empty string as the package # list in this case. by_regex = self.all_pkgs_by_name_regex verify_list = filter(None, map(by_regex, packages)) # No packages after regex match? if not verify_list: return None 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 # vim: set et ts=4 sw=4 :