diff --git a/SOURCES/sos-3.6-centos-branding.patch b/SOURCES/sos-3.6-centos-branding.patch deleted file mode 100644 index f88d36e..0000000 --- a/SOURCES/sos-3.6-centos-branding.patch +++ /dev/null @@ -1,105 +0,0 @@ -diff -uNrp sos-3.6.orig/sos/policies/redhat.py sos-3.6/sos/policies/redhat.py ---- sos-3.6.orig/sos/policies/redhat.py 2018-11-04 17:44:59.513116585 +0000 -+++ sos-3.6/sos/policies/redhat.py 2018-11-04 17:53:28.333731059 +0000 -@@ -32,9 +32,9 @@ OS_RELEASE = "/etc/os-release" - - - class RedHatPolicy(LinuxPolicy): -- distro = "Red Hat" -- vendor = "Red Hat" -- vendor_url = "http://www.redhat.com/" -+ distro = "CentOS" -+ vendor = "CentOS" -+ vendor_url = "http://www,centos.org/" - _redhat_release = '/etc/redhat-release' - _tmp_dir = "/var/tmp" - _rpmq_cmd = 'rpm -qa --queryformat "%{NAME}|%{VERSION}|%{RELEASE}\\n"' -@@ -92,9 +92,9 @@ class RedHatPolicy(LinuxPolicy): - - @classmethod - def check(cls): -- """This method checks to see if we are running on Red Hat. It must be -+ """This method checks to see if we are running on CentOS. It must be - overriden by concrete subclasses to return True when running on a -- Fedora, RHEL or other Red Hat distribution or False otherwise.""" -+ Fedora, RHEL or CentOS distribution or False otherwise.""" - return False - - def check_usrmove(self, pkgs): -@@ -185,7 +185,7 @@ class RedHatPolicy(LinuxPolicy): - return self.host_name() - - --# Container environment variables on Red Hat systems. -+# Container environment variables on CentOS systems. - ENV_CONTAINER = 'container' - ENV_HOST_SYSROOT = 'HOST' - -@@ -195,22 +195,22 @@ _opts_all_logs_verify = SoSOptions(all_l - _opts_all_logs_no_lsof = SoSOptions(all_logs=True, - plugopts=['process.lsof=off']) - --RHEL_RELEASE_STR = "Red Hat Enterprise Linux" -+RHEL_RELEASE_STR = "CentOS Linux" - - RHV = "rhv" --RHV_DESC = "Red Hat Virtualization" -+RHV_DESC = "CentOS Virtualization" - - RHEL = "rhel" - RHEL_DESC = RHEL_RELEASE_STR - - RHOSP = "rhosp" --RHOSP_DESC = "Red Hat OpenStack Platform" -+RHOSP_DESC = "RDO" - - RHOCP = "ocp" --RHOCP_DESC = "OpenShift Container Platform by Red Hat" -+RHOCP_DESC = "OpenShift" - - RH_SATELLITE = "satellite" --RH_SATELLITE_DESC = "Red Hat Satellite" -+RH_SATELLITE_DESC = "Satellite" - - NOTE_SIZE = "This preset may increase report size" - NOTE_TIME = "This preset may increase report run time" -@@ -230,9 +230,9 @@ rhel_presets = { - - - class RHELPolicy(RedHatPolicy): -- distro = RHEL_RELEASE_STR -- vendor = "Red Hat" -- vendor_url = "https://access.redhat.com/support/" -+ distro = "CentOS Linux" -+ vendor = "CentOS" -+ vendor_url = "https://wiki.centos.org/" - msg = _("""\ - This command will collect diagnostic and configuration \ - information from this %(distro)s system and installed \ -@@ -262,7 +262,7 @@ No changes will be made to system config - def check(cls): - """Test to see if the running host is a RHEL installation. - -- Checks for the presence of the "Red Hat Enterprise Linux" -+ Checks for the presence of the "CentOS Linux" - release string at the beginning of the NAME field in the - `/etc/os-release` file and returns ``True`` if it is - found, and ``False`` otherwise. -@@ -324,7 +324,7 @@ No changes will be made to system config - - ATOMIC = "atomic" - ATOMIC_RELEASE_STR = "Atomic" --ATOMIC_DESC = "Red Hat Enterprise Linux Atomic Host" -+ATOMIC_DESC = "CentOS Linux Atomic Host" - - atomic_presets = { - ATOMIC: PresetDefaults(name=ATOMIC, desc=ATOMIC_DESC, note=NOTE_TIME, -@@ -333,7 +333,7 @@ atomic_presets = { - - - class RedHatAtomicPolicy(RHELPolicy): -- distro = "Red Hat Atomic Host" -+ distro = "CentOS Atomic Host" - msg = _("""\ - This command will collect diagnostic and configuration \ - information from this %(distro)s system. diff --git a/SOURCES/sos-bz1715470-rhv-postgres-from-scl.patch b/SOURCES/sos-bz1715470-rhv-postgres-from-scl.patch new file mode 100644 index 0000000..48fd560 --- /dev/null +++ b/SOURCES/sos-bz1715470-rhv-postgres-from-scl.patch @@ -0,0 +1,489 @@ +From 6db459e2b21a798d93cc79e705e8e02f1bbd24c1 Mon Sep 17 00:00:00 2001 +From: Jake Hunsaker +Date: Tue, 24 Jul 2018 17:40:25 -0400 +Subject: [PATCH] [Policies|Plugins] Add services member + +Adds a services member to facilitate plugin enablement. This is tied to +a new InitSystem class that gets attached to policies. The InitSystem +class is used to determine services that are present on the system and +what those service statuses currently are (e.g. enabled/disable). + +Plugins can now specify a set of services to enable the plugin on if +that service exists on the system, similar to the file, command, and +package checks. + +Additionally, the Plugin class now has methods to check on service +states, and make decisions based off of. For example: + + def setup(self): + if self.is_service('foobar'): + self.add_cmd_output('barfoo') + +Currently, only systemd has actual functionality for this. The base +InitSystem inherited by policies by default will always return False for +service checks, thus resulting in the same behavior as before this +change. + +The Red Hat family of distributions has been set to systemd, as all +current versions of those distributions use systemd. + +Closes: #83 +Resolves: #1387 + +Signed-off-by: Jake Hunsaker +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/__init__.py | 31 +++++++++-- + sos/policies/__init__.py | 115 ++++++++++++++++++++++++++++++++++++++- + sos/policies/redhat.py | 1 + + 3 files changed, 142 insertions(+), 5 deletions(-) + +diff --git a/sos/plugins/__init__.py b/sos/plugins/__init__.py +index 82fef18e5..252de4d05 100644 +--- a/sos/plugins/__init__.py ++++ b/sos/plugins/__init__.py +@@ -123,6 +123,7 @@ class Plugin(object): + files = () + commands = () + kernel_mods = () ++ services = () + archive = None + profiles = () + sysroot = '/' +@@ -202,6 +203,22 @@ def is_installed(self, package_name): + '''Is the package $package_name installed?''' + return self.policy.pkg_by_name(package_name) is not None + ++ def is_service(self, name): ++ '''Does the service $name exist on the system?''' ++ return self.policy.init_system.is_service(name) ++ ++ def service_is_enabled(self, name): ++ '''Is the service $name enabled?''' ++ return self.policy.init_system.is_enabled(name) ++ ++ def service_is_disabled(self, name): ++ '''Is the service $name disabled?''' ++ return self.policy.init_system.is_disabled(name) ++ ++ def get_service_status(self, name): ++ '''Return the reported status for service $name''' ++ return self.policy.init_system.get_service_status(name) ++ + def do_cmd_private_sub(self, cmd): + '''Remove certificate and key output archived by sosreport. cmd + is the command name from which output is collected (i.e. exlcuding +@@ -977,7 +994,8 @@ def check_enabled(self): + overridden. + """ + # some files or packages have been specified for this package +- if any([self.files, self.packages, self.commands, self.kernel_mods]): ++ if any([self.files, self.packages, self.commands, self.kernel_mods, ++ self.services]): + if isinstance(self.files, six.string_types): + self.files = [self.files] + +@@ -990,6 +1008,9 @@ def check_enabled(self): + if isinstance(self.kernel_mods, six.string_types): + self.kernel_mods = [self.kernel_mods] + ++ if isinstance(self.services, six.string_types): ++ self.services = [self.services] ++ + if isinstance(self, SCLPlugin): + # save SCLs that match files or packages + type(self)._scls_matched = [] +@@ -1005,7 +1026,8 @@ def check_enabled(self): + + return self._files_pkgs_or_cmds_present(self.files, + self.packages, +- self.commands) ++ self.commands, ++ self.services) + + if isinstance(self, SCLPlugin): + # if files and packages weren't specified, we take all SCLs +@@ -1013,7 +1035,7 @@ def check_enabled(self): + + return True + +- def _files_pkgs_or_cmds_present(self, files, packages, commands): ++ def _files_pkgs_or_cmds_present(self, files, packages, commands, services): + kernel_mods = self.policy.lsmod() + + def have_kmod(kmod): +@@ -1022,7 +1044,8 @@ def have_kmod(kmod): + return (any(os.path.exists(fname) for fname in files) or + any(self.is_installed(pkg) for pkg in packages) or + any(is_executable(cmd) for cmd in commands) or +- any(have_kmod(kmod) for kmod in self.kernel_mods)) ++ any(have_kmod(kmod) for kmod in self.kernel_mods) or ++ any(self.is_service(svc) for svc in services)) + + def default_enabled(self): + """This decides whether a plugin should be automatically loaded or +diff --git a/sos/policies/__init__.py b/sos/policies/__init__.py +index 65d8aac63..d6255d3ee 100644 +--- a/sos/policies/__init__.py ++++ b/sos/policies/__init__.py +@@ -13,7 +13,8 @@ + + from sos.utilities import (ImporterHelper, + import_module, +- shell_out) ++ shell_out, ++ sos_get_command_output) + from sos.plugins import IndependentPlugin, ExperimentalPlugin + from sos import _sos as _ + from sos import SoSOptions, _arg_names +@@ -49,6 +50,113 @@ def load(cache={}, sysroot=None): + return cache['policy'] + + ++class InitSystem(object): ++ """Encapsulates an init system to provide service-oriented functions to ++ sos. ++ ++ This should be used to query the status of services, such as if they are ++ enabled or disabled on boot, or if the service is currently running. ++ """ ++ ++ def __init__(self, init_cmd=None, list_cmd=None, query_cmd=None): ++ ++ self.services = {} ++ ++ self.init_cmd = init_cmd ++ self.list_cmd = "%s %s" % (self.init_cmd, list_cmd) or None ++ self.query_cmd = "%s %s" % (self.init_cmd, query_cmd) or None ++ ++ self.load_all_services() ++ ++ def is_enabled(self, name): ++ """Check if given service name is enabled """ ++ if self.services and name in self.services: ++ return self.services[name]['config'] == 'enabled' ++ return False ++ ++ def is_disabled(self, name): ++ """Check if a given service name is disabled """ ++ if self.services and name in self.services: ++ return self.services[name]['config'] == 'disabled' ++ return False ++ ++ def is_service(self, name): ++ """Checks if the given service name exists on the system at all, this ++ does not check for the service status ++ """ ++ return name in self.services ++ ++ def load_all_services(self): ++ """This loads all services known to the init system into a dict. ++ The dict should be keyed by the service name, and contain a dict of the ++ name and service status ++ """ ++ pass ++ ++ def _query_service(self, name): ++ """Query an individual service""" ++ if self.query_cmd: ++ res = sos_get_command_output("%s %s" % (self.query_cmd, name)) ++ if res['status'] == 0: ++ return res ++ else: ++ return None ++ return None ++ ++ def parse_query(self, output): ++ """Parses the output returned by the query command to make a ++ determination of what the state of the service is ++ ++ This should be overriden by anything that subclasses InitSystem ++ """ ++ return output ++ ++ def get_service_status(self, name): ++ """Returns the status for the given service name along with the output ++ of the query command ++ """ ++ svc = self._query_service(name) ++ if svc is not None: ++ return {'name': name, ++ 'status': self.parse_query(svc['output']), ++ 'output': svc['output'] ++ } ++ else: ++ return {'name': name, ++ 'status': 'missing', ++ 'output': '' ++ } ++ ++ ++class SystemdInit(InitSystem): ++ ++ def __init__(self): ++ super(SystemdInit, self).__init__( ++ init_cmd='systemctl', ++ list_cmd='list-unit-files --type=service', ++ query_cmd='status' ++ ) ++ ++ def parse_query(self, output): ++ for line in output.splitlines(): ++ if line.strip().startswith('Active:'): ++ return line.split()[1] ++ return 'unknown' ++ ++ def load_all_services(self): ++ svcs = shell_out(self.list_cmd).splitlines() ++ for line in svcs: ++ try: ++ name = line.split('.service')[0] ++ config = line.split()[1] ++ self.services[name] = { ++ 'name': name, ++ 'config': config ++ } ++ except IndexError: ++ pass ++ ++ + class PackageManager(object): + """Encapsulates a package manager. If you provide a query_command to the + constructor it should print each package on the system in the following +@@ -676,11 +784,16 @@ class LinuxPolicy(Policy): + distro = "Linux" + vendor = "None" + PATH = "/bin:/sbin:/usr/bin:/usr/sbin" ++ init = None + + _preferred_hash_name = None + + def __init__(self, sysroot=None): + super(LinuxPolicy, self).__init__(sysroot=sysroot) ++ if self.init == 'systemd': ++ self.init_system = SystemdInit() ++ else: ++ self.init_system = InitSystem() + + def get_preferred_hash_name(self): + +diff --git a/sos/policies/redhat.py b/sos/policies/redhat.py +index 5bfbade28..b494de3c4 100644 +--- a/sos/policies/redhat.py ++++ b/sos/policies/redhat.py +@@ -45,6 +45,7 @@ class RedHatPolicy(LinuxPolicy): + _host_sysroot = '/' + default_scl_prefix = '/opt/rh' + name_pattern = 'friendly' ++ init = 'systemd' + + def __init__(self, sysroot=None): + super(RedHatPolicy, self).__init__(sysroot=sysroot) +From 7b9284e948f2e9076c92741ed5b95fec7934af8d Mon Sep 17 00:00:00 2001 +From: Jake Hunsaker +Date: Fri, 15 Feb 2019 16:03:53 -0500 +Subject: [PATCH] [policy|plugin] Add 'is_running' check for services + +Adds a method to the InitSystem class used by policies and plugins to +check if a given service name is running. Plugins can make use of this +through the new self.service_is_running() method. + +For policies that use the base InitSystem class, this method will always +return True as the service_is_running() method is likely to be used when +determining if we should run commands or not, and we do not want to +incorrectly stop running those commands where they would collect +meaningful output today. + +The SystemD init system for policies properly checks to see if the given +service is active or not when reporting is the service is running. + +Resolves: #1567 + +Signed-off-by: Jake Hunsaker +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/__init__.py | 6 +++++- + sos/policies/__init__.py | 22 ++++++++++++++++++---- + 2 files changed, 23 insertions(+), 5 deletions(-) + +diff --git a/sos/plugins/__init__.py b/sos/plugins/__init__.py +index 47b028a85..030e7a305 100644 +--- a/sos/plugins/__init__.py ++++ b/sos/plugins/__init__.py +@@ -215,9 +215,13 @@ def service_is_disabled(self, name): + '''Is the service $name disabled?''' + return self.policy.init_system.is_disabled(name) + ++ def service_is_running(self, name): ++ '''Is the service $name currently running?''' ++ return self.policy.init_system.is_running(name) ++ + def get_service_status(self, name): + '''Return the reported status for service $name''' +- return self.policy.init_system.get_service_status(name) ++ return self.policy.init_system.get_service_status(name)['status'] + + def do_cmd_private_sub(self, cmd): + '''Remove certificate and key output archived by sosreport. cmd +diff --git a/sos/policies/__init__.py b/sos/policies/__init__.py +index d6255d3ee..d0b180152 100644 +--- a/sos/policies/__init__.py ++++ b/sos/policies/__init__.py +@@ -86,6 +86,17 @@ def is_service(self, name): + """ + return name in self.services + ++ def is_running(self, name): ++ """Checks if the given service name is in a running state. ++ ++ This should be overridden by initsystems that subclass InitSystem ++ """ ++ # This is going to be primarily used in gating if service related ++ # commands are going to be run or not. Default to always returning ++ # True when an actual init system is not specified by policy so that ++ # we don't inadvertantly restrict sosreports on those systems ++ return True ++ + def load_all_services(self): + """This loads all services known to the init system into a dict. + The dict should be keyed by the service name, and contain a dict of the +@@ -96,10 +107,9 @@ def load_all_services(self): + def _query_service(self, name): + """Query an individual service""" + if self.query_cmd: +- res = sos_get_command_output("%s %s" % (self.query_cmd, name)) +- if res['status'] == 0: +- return res +- else: ++ try: ++ return sos_get_command_output("%s %s" % (self.query_cmd, name)) ++ except Exception: + return None + return None + +@@ -156,6 +166,10 @@ def load_all_services(self): + except IndexError: + pass + ++ def is_running(self, name): ++ svc = self.get_service_status(name) ++ return svc['status'] == 'active' ++ + + class PackageManager(object): + """Encapsulates a package manager. If you provide a query_command to the +From 3e736ad53d254aba8795b3d5d8ce0ec4f827ab1c Mon Sep 17 00:00:00 2001 +From: Jake Hunsaker +Date: Fri, 8 Feb 2019 13:19:56 -0500 +Subject: [PATCH] [postgresql] Use postgres 10 scl if installed + +Updates the plugin to check if the specified SCL is running, as some +systems may have multiple SCL versions installed, but only one will be +running at a time. We now use the running version for a pgdump. + +This is primarily aimed at RHV environments as 4.3 and later use version +10. + +Signed-off-by: Jake Hunsaker +--- + sos/plugins/postgresql.py | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/sos/plugins/postgresql.py b/sos/plugins/postgresql.py +index aef431f8a..e641c3b44 100644 +--- a/sos/plugins/postgresql.py ++++ b/sos/plugins/postgresql.py +@@ -80,14 +80,25 @@ def setup(self): + + class RedHatPostgreSQL(PostgreSQL, SCLPlugin): + +- packages = ('postgresql', 'rh-postgresql95-postgresql-server', ) ++ packages = ( ++ 'postgresql', ++ 'rh-postgresql95-postgresql-server', ++ 'rh-postgresql10-postgresql-server' ++ ) + + def setup(self): + super(RedHatPostgreSQL, self).setup() + +- scl = "rh-postgresql95" + pghome = self.get_option("pghome") + ++ scl = None ++ for pkg in self.packages[1:]: ++ # The scl name, package name, and service name all differ slightly ++ # but is at least consistent in doing so across versions, so we ++ # need to do some mangling here ++ if self.service_is_running(pkg.replace('-server', '')): ++ scl = pkg.split('-postgresql-')[0] ++ + # Copy PostgreSQL log files. + for filename in find("*.log", pghome): + self.add_copy_spec(filename) +@@ -111,7 +122,7 @@ def setup(self): + ) + ) + +- if scl in self.scls_matched: ++ if scl and scl in self.scls_matched: + self.do_pg_dump(scl=scl, filename="pgdump-scl-%s.tar" % scl) + + +From 0ba743bbf9df335dd47ec45a450e63d72d7ce494 Mon Sep 17 00:00:00 2001 +From: Pavel Moravec +Date: Wed, 5 Sep 2018 12:34:48 +0200 +Subject: [PATCH] [plugins] fix 6db459e for SCL services + +Calling _files_pkgs_or_cmds_present for SCLs lacks "services" +argument that was added in 6db459e commit. + +Also it is worth renaming the method to more generic +_check_plugin_triggers . + +Resolves: #1416 + +Signed-off-by: Pavel Moravec +--- + sos/plugins/__init__.py | 18 ++++++++++-------- + 1 file changed, 10 insertions(+), 8 deletions(-) + +diff --git a/sos/plugins/__init__.py b/sos/plugins/__init__.py +index 97f3cc592..3abe29db6 100644 +--- a/sos/plugins/__init__.py ++++ b/sos/plugins/__init__.py +@@ -1033,16 +1033,18 @@ def check_enabled(self): + files = [f % {"scl_name": scl} for f in self.files] + packages = [p % {"scl_name": scl} for p in self.packages] + commands = [c % {"scl_name": scl} for c in self.commands] +- if self._files_pkgs_or_cmds_present(files, +- packages, +- commands): ++ services = [s % {"scl_name": scl} for s in self.services] ++ if self._check_plugin_triggers(files, ++ packages, ++ commands, ++ services): + type(self)._scls_matched.append(scl) + return len(type(self)._scls_matched) > 0 + +- return self._files_pkgs_or_cmds_present(self.files, +- self.packages, +- self.commands, +- self.services) ++ return self._check_plugin_triggers(self.files, ++ self.packages, ++ self.commands, ++ self.services) + + if isinstance(self, SCLPlugin): + # if files and packages weren't specified, we take all SCLs +@@ -1050,7 +1052,7 @@ def check_enabled(self): + + return True + +- def _files_pkgs_or_cmds_present(self, files, packages, commands, services): ++ def _check_plugin_triggers(self, files, packages, commands, services): + kernel_mods = self.policy.lsmod() + + def have_kmod(kmod): diff --git a/SPECS/sos.spec b/SPECS/sos.spec index 5e2f5c8..b0316f9 100644 --- a/SPECS/sos.spec +++ b/SPECS/sos.spec @@ -2,7 +2,7 @@ Summary: A set of tools to gather troubleshooting information from a system Name: sos Version: 3.6 -Release: 17%{?dist} +Release: 19%{?dist} Group: Applications/System Source0: https://github.com/sosreport/sos/archive/%{version}.tar.gz License: GPLv2+ @@ -38,7 +38,7 @@ Patch17: sos-bz1658571-postgresql-collect-full-dump.patch Patch18: sos-bz1669045-rhcos-policy-and-plugins.patch Patch19: sos-bz1679238-crio-plugin.patch Patch20: sos-bz1690999-docker-skip-system-df.patch -Patch21: sos-3.6-centos-branding.patch +Patch21: sos-bz1715470-rhv-postgres-from-scl.patch %description Sos is a set of tools that gathers information about system @@ -93,8 +93,9 @@ rm -rf ${RPM_BUILD_ROOT} %config(noreplace) %{_sysconfdir}/sos.conf %changelog -* Tue Apr 23 2019 CentOS Sources - 3.6-17.el7.centos -- Roll in CentOS Branding +* Thu May 30 2019 Pavel Moravec = 3.6-19 +- [postgresql] Use postgres 10 scl if installed + Resolves: bz1715470 * Wed Mar 20 2019 Pavel Moravec = 3.6-17 - [docker] do not collect 'system df' by default