aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sos/policies/distros/suse.py197
1 files changed, 179 insertions, 18 deletions
diff --git a/sos/policies/distros/suse.py b/sos/policies/distros/suse.py
index 8c7900e5..d33053fc 100644
--- a/sos/policies/distros/suse.py
+++ b/sos/policies/distros/suse.py
@@ -9,18 +9,34 @@
import os
import sys
+import re
from sos.report.plugins import RedHatPlugin, SuSEPlugin
from sos.policies.distros import LinuxPolicy
+from sos.policies.package_managers import PackageManager
from sos.policies.package_managers.rpm import RpmPackageManager
+from sos.presets import PresetDefaults
from sos import _sos as _
+from sos import SoSOptions
+OS_RELEASE = "/etc/os-release"
-class SuSEPolicy(LinuxPolicy):
- distro = "SuSE"
- vendor = "SuSE"
+
+class SUSEPolicy(LinuxPolicy):
+ distro = "SUSE"
+ vendor = "SUSE"
vendor_urls = [('Distribution Website', 'https://www.suse.com/')]
+ vendor_url = "https://www.suse.com/"
_tmp_dir = "/var/tmp"
+ _rpmq_cmd = 'rpm -qa --queryformat "%{NAME}|%{VERSION}|%{RELEASE}\\n"'
+ _rpmql_cmd = 'rpm -qal'
+ _rpmv_cmd = 'rpm -V'
+ _rpmv_filter = ["debuginfo", "-devel"]
+ _in_container = False
+ _host_sysroot = '/'
+ default_scl_prefix = '/opt/suse'
+ name_pattern = 'friendly'
+ init = 'systemd'
def __init__(self, sysroot=None, init=None, probe_runtime=True,
remote_exec=None):
@@ -41,26 +57,170 @@ class SuSEPolicy(LinuxPolicy):
self.PATH += os.pathsep + "/usr/local/bin"
self.PATH += os.pathsep + "/usr/local/sbin"
self.set_exec_path()
+ self.load_presets()
@classmethod
def check(cls, remote=''):
"""This method checks to see if we are running on SuSE. It must be
overriden by concrete subclasses to return True when running on an
- OpenSuSE, SLES or other Suse distribution and False otherwise."""
+ OpenSUSE, SLES or other Suse distribution and False otherwise."""
return False
+ def check_usrmove(self, pkgs):
+ """Test whether the running system implements UsrMove.
+
+ If the 'filesystem' package is present, it will check that the
+ version is greater than 3. If the package is not present the
+ '/bin' and '/sbin' paths are checked and UsrMove is assumed
+ if both are symbolic links.
+
+ :param pkgs: a packages dictionary
+ """
+ if 'filesystem' not in pkgs:
+ return os.path.islink('/bin') and os.path.islink('/sbin')
+ else:
+ filesys_version = pkgs['filesystem']['version']
+ return True if filesys_version[0] == '3' else False
+
+ def mangle_package_path(self, files):
+ """Mangle paths for post-UsrMove systems.
+
+ If the system implements UsrMove, all files will be in
+ '/usr/[s]bin'. This method substitutes all the /[s]bin
+ references in the 'files' list with '/usr/[s]bin'.
+
+ :param files: the list of package managed files
+ """
+ paths = []
+
+ def transform_path(path):
+ # Some packages actually own paths in /bin: in this case,
+ # duplicate the path as both the / and /usr version.
+ skip_paths = ["/bin/rpm", "/bin/mailx"]
+ if path in skip_paths:
+ return (path, os.path.join("/usr", path[1:]))
+ return (re.sub(r'(^)(/s?bin)', r'\1/usr\2', path),)
+
+ if self.usrmove:
+ for f in files:
+ paths.extend(transform_path(f))
+ return paths
+ else:
+ return files
+
+ def _container_init(self):
+ """Check if sos is running in a container and perform container
+ specific initialisation based on ENV_HOST_SYSROOT.
+ """
+ if ENV_CONTAINER in os.environ:
+ if os.environ[ENV_CONTAINER] in ['docker', 'oci']:
+ self._in_container = True
+ if ENV_HOST_SYSROOT in os.environ:
+ self._host_sysroot = os.environ[ENV_HOST_SYSROOT]
+ use_sysroot = self._in_container and self._host_sysroot != '/'
+ if use_sysroot:
+ host_tmp_dir = os.path.abspath(self._host_sysroot + self._tmp_dir)
+ self._tmp_dir = host_tmp_dir
+ return self._host_sysroot if use_sysroot else None
+
+ def runlevel_by_service(self, name):
+ from subprocess import Popen, PIPE
+ ret = []
+ p = Popen("LC_ALL=C /sbin/chkconfig --list %s" % name,
+ shell=True,
+ stdout=PIPE,
+ stderr=PIPE,
+ bufsize=-1,
+ close_fds=True)
+ out, err = p.communicate()
+ if err:
+ return ret
+ for tabs in out.split()[1:]:
+ try:
+ (runlevel, onoff) = tabs.split(":", 1)
+ except IndexError:
+ pass
+ else:
+ if onoff == "on":
+ ret.append(int(runlevel))
+ return ret
+
def get_tmp_dir(self, opt_tmp_dir):
if not opt_tmp_dir:
return self._tmp_dir
return opt_tmp_dir
- def get_local_name(self):
- return self.host_name()
+
+# Container environment variables on SUSE systems.
+ENV_CONTAINER = 'container'
+ENV_HOST_SYSROOT = 'HOST'
+
+_opts_verify = SoSOptions(verify=True)
+_opts_all_logs = SoSOptions(all_logs=True)
+_opts_all_logs_verify = SoSOptions(all_logs=True, verify=True)
+_opts_all_logs_no_lsof = SoSOptions(all_logs=True,
+ plugopts=['process.lsof=off'])
+_cb_plugs = ['abrt', 'block', 'boot', 'dnf', 'dracut', 'filesys', 'grub2',
+ 'hardware', 'host', 'kernel', 'logs', 'lvm2', 'memory', 'rpm',
+ 'process', 'systemd', 'yum', 'xfs']
+
+SLE_RELEASE_STR = "SUSE Enterprise Linux"
+
+RHV = "rhv"
+RHV_DESC = "SUSE Virtualization"
+
+SLE = "rhel"
+SLE_DESC = SLE_RELEASE_STR
+
+RHOSP = "rhosp"
+RHOSP_DESC = "SUSE OpenStack Platform"
+
+RHOCP = "ocp"
+RHOCP_DESC = "OpenShift Container Platform by SUSE"
+
+RH_SATELLITE = "satellite"
+RH_SATELLITE_DESC = "SUSE Satellite"
+SAT_OPTS = SoSOptions(verify=True, plugopts=['apache.log=on'])
+
+CB = "cantboot"
+CB_DESC = "For use when normal system startup fails"
+CB_OPTS = SoSOptions(verify=True, all_logs=True, onlyplugins=_cb_plugs)
+CB_NOTE = ("Data collection will be limited to a boot-affecting scope")
+
+NOTE_SIZE = "This preset may increase report size"
+NOTE_TIME = "This preset may increase report run time"
+NOTE_SIZE_TIME = "This preset may increase report size and run time"
+
+rhel_presets = {
+ RHV: PresetDefaults(name=RHV, desc=RHV_DESC, note=NOTE_TIME,
+ opts=_opts_verify),
+ SLE: PresetDefaults(name=SLE, desc=SLE_DESC),
+ RHOSP: PresetDefaults(name=RHOSP, desc=RHOSP_DESC, note=NOTE_SIZE,
+ opts=_opts_all_logs_no_lsof),
+ RHOCP: PresetDefaults(name=RHOCP, desc=RHOCP_DESC, note=NOTE_SIZE_TIME,
+ opts=_opts_all_logs_verify),
+ RH_SATELLITE: PresetDefaults(name=RH_SATELLITE, desc=RH_SATELLITE_DESC,
+ note=NOTE_TIME, opts=SAT_OPTS),
+ CB: PresetDefaults(name=CB, desc=CB_DESC, note=CB_NOTE, opts=CB_OPTS)
+}
+
+# Legal disclaimer text for SUSE products
+disclaimer_text = """
+Any information provided to %(vendor)s will be treated in \
+accordance with the published support policies at:\n
+ %(vendor_url)s
+
+The generated archive may contain data considered sensitive \
+and its content should be reviewed by the originating \
+organization before being passed to any third party.
+
+No changes will be made to system configuration.
+"""
-class OpenSuSEPolicy(SuSEPolicy):
- distro = "OpenSuSE"
- vendor = "SuSE"
+class SLEPolicy(SUSEPolicy):
+ distro = SLE_RELEASE_STR
+ vendor = "SUSE"
vendor_urls = [('Community Website', 'https://www.opensuse.org/')]
msg = _("""\
This command will collect diagnostic and configuration \
@@ -70,10 +230,7 @@ applications.
An archive containing the collected information will be \
generated in %(tmpdir)s and may be provided to a %(vendor)s \
support representative.
-
-No changes will be made to system configuration.
-%(vendor_text)s
-""")
+""" + disclaimer_text + "%(vendor_text)s\n")
def __init__(self, sysroot=None, init=None, probe_runtime=True,
remote_exec=None):
@@ -85,8 +242,12 @@ No changes will be made to system configuration.
def check(cls, remote):
"""This method checks to see if we are running on SuSE.
"""
-
- if remote:
- return cls.distro in remote
-
- return os.path.isfile('/etc/SUSE-brand')
+ with open('/etc/os-release') as inf:
+ for l in inf:
+ if l.startswith('NAME'):
+ return 'SUSE' in l.split('=')[1].strip(' "\t\n')
+
+ def opensuse_version(self):
+ pkg = self.pkg_by_name("openSUSE-release") or \
+ self.all_pkgs_by_name_regex("openSUSE-release-.*")[-1]
+ return int(pkg["version"])