!20 Update to 3.8

From: @bzg1107
Reviewed-by: @overweight
Signed-off-by: @overweight
This commit is contained in:
openeuler-ci-bot 2021-09-16 02:52:17 +00:00 committed by Gitee
commit 6a71f25738
18 changed files with 81 additions and 970 deletions

Binary file not shown.

View File

@ -0,0 +1,45 @@
From dcb9273e1f5f55fec2957629a5a69ca396f28c51 Mon Sep 17 00:00:00 2001
From: root <root@localhost.localdomain>
Date: Mon, 19 Jul 2021 15:48:03 +0800
Subject: [PATCH] add uniontech os support
---
sos/policies/uniontech.py | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
create mode 100644 sos/policies/uniontech.py
diff --git a/sos/policies/uniontech.py b/sos/policies/uniontech.py
new file mode 100644
index 0000000..cd30136
--- /dev/null
+++ b/sos/policies/uniontech.py
@@ -0,0 +1,26 @@
+from __future__ import print_function
+
+from sos.plugins import RedHatPlugin
+from sos.policies.redhat import RedHatPolicy, OS_RELEASE
+import os
+
+class UnionTechPolicy(RedHatPolicy):
+
+ distro = "UnionTech"
+ vendor = "the UnionTech Project"
+ vendor_url = "https://www.chinauos.com/"
+
+ def __init__(self, sysroot=None):
+ super(UnionTechPolicy, self).__init__(sysroot=sysroot)
+
+ @classmethod
+ def check(cls):
+ if not os.path.exists(OS_RELEASE):
+ return False
+
+ with open(OS_RELEASE, 'r') as f:
+ for line in f:
+ if line.startswith('NAME'):
+ if 'UnionTech' in line:
+ return True
+ return False
--
2.23.0

View File

@ -1,30 +0,0 @@
From 0ea62d1ea57f41c1b75ccb83e69fdda386a7d280 Mon Sep 17 00:00:00 2001
From: "Bryn M. Reeves" <bmr@redhat.com>
Date: Fri, 7 Sep 2018 13:00:52 -0400
Subject: [PATCH 0045/1146] [Plugin] fix exception raise in Plugin._copy_dir()
Use a naked 'raise' statement rather than raising the already caught
exception in _copy_dir(), so that the original stack and backtrace
are avaialable.
Signed-off-by: Bryn M. Reeves <bmr@redhat.com>
---
sos/plugins/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sos/plugins/__init__.py b/sos/plugins/__init__.py
index 252de4d0..ac2c0bc8 100644
--- a/sos/plugins/__init__.py
+++ b/sos/plugins/__init__.py
@@ -401,7 +401,7 @@ class Plugin(object):
msg = "Too many levels of symbolic links copying"
self._log_error("_copy_dir: %s '%s'" % (msg, srcpath))
return
- raise e
+ raise
def _get_dest_for_srcpath(self, srcpath):
if self.use_sysroot():
--
2.26.0.windows.1

View File

@ -1,284 +0,0 @@
From 6db459e2b21a798d93cc79e705e8e02f1bbd24c1 Mon Sep 17 00:00:00 2001
From: Jake Hunsaker <jhunsake@redhat.com>
Date: Tue, 24 Jul 2018 17:40:25 -0400
Subject: [PATCH 0033/1146] [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 <jhunsake@redhat.com>
Signed-off-by: Bryn M. Reeves <bmr@redhat.com>
---
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 82fef18e..252de4d0 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 @@ class Plugin(object):
'''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 @@ class Plugin(object):
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 @@ class Plugin(object):
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 @@ class Plugin(object):
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 @@ class Plugin(object):
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 @@ class Plugin(object):
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 65d8aac6..d6255d3e 100644
--- a/sos/policies/__init__.py
+++ b/sos/policies/__init__.py
@@ -13,7 +13,8 @@ from os import environ
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 5bfbade2..b494de3c 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)
--
2.26.0.windows.1

View File

@ -1,46 +0,0 @@
From d5b1d349b868e66a4001c23dae7afa05daaca907 Mon Sep 17 00:00:00 2001
From: Pavel Moravec <pmoravec@redhat.com>
Date: Wed, 22 Aug 2018 10:35:58 +0200
Subject: [PATCH 0022/1146] [archive] Dont copystat /sys and /proc paths
Stop copying extended attributes of files under /sys and /proc
that can raise SELinux denials on that attempt.
Resolves: #1399
Signed-off-by: Pavel Moravec <pmoravec@redhat.com>
---
sos/archive.py | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/sos/archive.py b/sos/archive.py
index fdf6f9a8..5d99170f 100644
--- a/sos/archive.py
+++ b/sos/archive.py
@@ -251,16 +251,17 @@ class FileCacheArchive(Archive):
pass
else:
self.log_info("caught '%s' copying '%s'" % (e, src))
- try:
- shutil.copystat(src, dest)
- except OSError:
- # SELinux xattrs in /proc and /sys throw this
- pass
+ # copy file attributes, skip SELinux xattrs for /sys and /proc
try:
stat = os.stat(src)
+ if src.startswith("/sys/") or src.startswith("/proc/"):
+ shutil.copymode(src, dest)
+ os.utime(dest, ns=(stat.st_atime_ns, stat.st_mtime_ns))
+ else:
+ shutil.copystat(src, dest)
os.chown(dest, stat.st_uid, stat.st_gid)
except Exception as e:
- self.log_debug("caught '%s' setting ownership of '%s'"
+ self.log_debug("caught '%s' setting attributes of '%s'"
% (e, dest))
file_name = "'%s'" % src
else:
--
2.26.0.windows.1

View File

@ -1,85 +0,0 @@
From 322f4a517ae336cc1443f9a399a0d15d45ec48b9 Mon Sep 17 00:00:00 2001
From: "Bryn M. Reeves" <bmr@redhat.com>
Date: Fri, 7 Sep 2018 13:11:03 -0400
Subject: [PATCH 0047/1146] [archive] add link follow-up to
FileCacheArchive.add_link()
Creating a link may trigger further actions in the archive: if the
link target is a regular file, we must copy that file into the
archive, and if the target is a symbolic link, then we must create
that link, and copy in the link target.
Handle this by calling add_file() or (recursively) add_link() in
order to create the missing pieces of the symlink chain.
These operations must take place outside of the path lock since
they do not modify the archive namespace and will call methods of
the Archive object that will attempt to re-acquire this lock.
Resolves: #1404
Signed-off-by: Bryn M. Reeves <bmr@redhat.com>
---
sos/archive.py | 38 +++++++++++++++++++++++++++++++++++---
1 file changed, 35 insertions(+), 3 deletions(-)
diff --git a/sos/archive.py b/sos/archive.py
index c256a01f..6db398fc 100644
--- a/sos/archive.py
+++ b/sos/archive.py
@@ -403,6 +403,7 @@ class FileCacheArchive(Archive):
% (dest, self._archive_root))
def add_link(self, source, link_name):
+ self.log_debug("adding symlink at '%s' -> '%s'" % (link_name, source))
with self._path_lock:
dest = self._check_path(link_name, P_LINK)
if not dest:
@@ -410,10 +411,41 @@ class FileCacheArchive(Archive):
if not os.path.lexists(dest):
os.symlink(source, dest)
- self.log_debug("added symlink at '%s' to '%s' in archive '%s'"
- % (dest, source, self._archive_root))
+ self.log_debug("added symlink at '%s' to '%s' in archive '%s'"
+ % (dest, source, self._archive_root))
+
+ # Follow-up must be outside the path lock: we recurse into
+ # other monitor methods that will attempt to reacquire it.
+
+ source_dir = os.path.dirname(link_name)
+ host_source = os.path.join(source_dir, source)
+ if not os.path.exists(self.dest_path(host_source)):
+ if os.path.islink(host_source):
+ link_dir = os.path.dirname(link_name)
+ link_name = os.path.normpath(os.path.join(link_dir, source))
+ dest_dir = os.path.dirname(link_name)
+ source = os.path.join(dest_dir, os.readlink(link_name))
+ source = os.path.relpath(source)
+ self.log_debug("Adding link %s -> %s for link follow up" %
+ (link_name, source))
+ self.add_link(source, link_path)
+ elif os.path.isdir(host_source):
+ self.log_debug("Adding dir %s for link follow up" % source)
+ self.add_dir(host_source)
+ elif os.path.isfile(host_source):
+ self.log_debug("Adding file %s for link follow up" % source)
+ self.add_file(host_source)
+ else:
+ self.log_debug("No link follow up: source=%s link_name=%s" %
+ (source, link_name))
- def add_dir(self, path):
+
+ def add_dir(self, path, copy=False):
+ """Create a directory in the archive.
+
+ :param path: the path in the host file system to add
+ """
+ # Establish path structure
with self._path_lock:
self._check_path(path, P_DIR)
--
2.26.0.windows.1

View File

@ -1,122 +0,0 @@
From d84c1cd6dedf51a8ed7b1a511585c0ac2db0f083 Mon Sep 17 00:00:00 2001
From: "Bryn M. Reeves" <bmr@redhat.com>
Date: Wed, 5 Sep 2018 12:46:16 +0100
Subject: [PATCH 0046/1146] [archive] fix leading path creation
Fix the creation of leading path components for both paths that
contain intermediate components that are symbolic links (with both
absolute and relative targets), and those that contain only
directory components.
Since symlinks may link to other files, and other symlinks, it is
necessary to handle these paths recursively and to include any
intermediate symlinked directories, or symlink targets in the set
of paths added to the archive.
Related: #1404
Signed-off-by: Bryn M. Reeves <bmr@redhat.com>
---
sos/archive.py | 41 ++++++++++++++++++++++++++++++++++-------
1 file changed, 34 insertions(+), 7 deletions(-)
diff --git a/sos/archive.py b/sos/archive.py
index 473af86..47c80c3 100644
--- a/sos/archive.py
+++ b/sos/archive.py
@@ -164,9 +164,24 @@ class FileCacheArchive(Archive):
The standard python `os.makedirs` is insufficient for our
needs: it will only create directories, and ignores the fact
that some path components may be symbolic links.
+
+ :param src: The source path in the host file system for which
+ leading components should be created, or the path
+ to an sos_* virtual directory inside the archive.
+
+ Host paths must be absolute (initial '/'), and
+ sos_* directory paths must be a path relative to
+ the root of the archive.
+
+ :param mode: An optional mode to be used when creating path
+ components.
+ :returns: A rewritten destination path in the case that one
+ or more symbolic links in intermediate components
+ of the path have altered the path destination.
"""
self.log_debug("Making leading paths for %s" % src)
root = self._archive_root
+ dest = src
def in_archive(path):
"""Test whether path ``path`` is inside the archive.
@@ -190,34 +205,42 @@ class FileCacheArchive(Archive):
path_comps.reverse()
abs_path = root
- rel_path = ""
+ src_path = "/"
# Check and create components as needed
for comp in path_comps:
abs_path = os.path.join(abs_path, comp)
+ # Do not create components that are above the archive root.
if not in_archive(abs_path):
continue
- rel_path = os.path.join(rel_path, comp)
- src_path = os.path.join("/", rel_path)
+ src_path = os.path.join(src_path, comp)
if not os.path.exists(abs_path):
self.log_debug("Making path %s" % abs_path)
if os.path.islink(src_path) and os.path.isdir(src_path):
target = os.readlink(src_path)
- abs_target = os.path.join(root, target)
+
+ # The directory containing the source in the host fs,
+ # adjusted for the current level of path creation.
+ target_dir = os.path.split(src_path)[0]
+
+ # The source path of the target in the host fs to be
+ # recursively copied.
+ target_src = os.path.join(target_dir, target)
# Recursively create leading components of target
- self._make_leading_paths(abs_target, mode=mode)
+ dest = self._make_leading_paths(target_src, mode=mode)
+ dest = os.path.normpath(dest)
self.log_debug("Making symlink '%s' -> '%s'" %
(abs_path, target))
- target = os.path.relpath(target)
os.symlink(target, abs_path)
else:
self.log_debug("Making directory %s" % abs_path)
os.mkdir(abs_path, mode)
+ return dest
def _check_path(self, src, path_type, dest=None):
"""Check a new destination path in the archive.
@@ -257,13 +280,17 @@ class FileCacheArchive(Archive):
if not dest_dir:
return dest
+ # Preserve destination basename for rewritten dest_dir
+ dest_name = os.path.split(src)[1]
+
# Check containing directory presence and path type
if os.path.exists(dest_dir) and not os.path.isdir(dest_dir):
raise ValueError("path '%s' exists and is not a directory" %
dest_dir)
elif not os.path.exists(dest_dir):
src_dir = src if path_type == P_DIR else os.path.split(src)[0]
- self._make_leading_paths(src_dir)
+ src_dir = self._make_leading_paths(src_dir)
+ dest = self.dest_path(os.path.join(src_dir, dest_name))
def is_special(mode):
return any([
--
2.13.7

View File

@ -1,30 +0,0 @@
From 3a2453c186084a2b7ef15702775809a76e13c45c Mon Sep 17 00:00:00 2001
From: "Bryn M. Reeves" <bmr@redhat.com>
Date: Tue, 11 Sep 2018 12:54:20 +0100
Subject: [PATCH 0051/1146] [archive] fix local variable name in
FileCacheArchive.add_link()
The 'link_path' local was renamed to 'link_name' to better match
other uses in the code.
Signed-off-by: Bryn M. Reeves <bmr@redhat.com>
---
sos/archive.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sos/archive.py b/sos/archive.py
index 4b30630b..528cfa57 100644
--- a/sos/archive.py
+++ b/sos/archive.py
@@ -428,7 +428,7 @@ class FileCacheArchive(Archive):
source = os.path.relpath(source)
self.log_debug("Adding link %s -> %s for link follow up" %
(link_name, source))
- self.add_link(source, link_path)
+ self.add_link(source, link_name)
elif os.path.isdir(host_source):
self.log_debug("Adding dir %s for link follow up" % source)
self.add_dir(host_source)
--
2.26.0.windows.1

View File

@ -1,34 +0,0 @@
From ca422720b74181b2433473428e29e90af59b3cf8 Mon Sep 17 00:00:00 2001
From: "Bryn M. Reeves" <bmr@redhat.com>
Date: Fri, 31 Aug 2018 12:55:51 +0100
Subject: [PATCH 0025/1146] [archive] normalise dest_dir in
FileCacheArchive._check_path()
Always set a valid dest_dir in _check_path() and do not assume
that it can be obtained by splitting the path: in the case of
a directory it is the unmodified 'dest' value.
Signed-off-by: Bryn M. Reeves <bmr@redhat.com>
---
sos/archive.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/sos/archive.py b/sos/archive.py
index ffa54036..903cc672 100644
--- a/sos/archive.py
+++ b/sos/archive.py
@@ -191,7 +191,10 @@ class FileCacheArchive(Archive):
copied now or `None` otherwise
"""
dest = dest or self.dest_path(src)
- dest_dir = os.path.split(dest)[0]
+ if path_type == P_DIR:
+ dest_dir = dest
+ else:
+ dest_dir = os.path.split(dest)[0]
if not dest_dir:
return dest
--
2.26.0.windows.1

View File

@ -1,28 +0,0 @@
From 6e79c4b4a4f32fa549708dbb8c8b9af73ab8ff61 Mon Sep 17 00:00:00 2001
From: "Bryn M. Reeves" <bmr@redhat.com>
Date: Mon, 10 Sep 2018 16:33:33 +0100
Subject: [PATCH 0048/1146] [archive] remove unused 'copy' arg from
FileCacheArchive.add_dir()
Signed-off-by: Bryn M. Reeves <bmr@redhat.com>
---
sos/archive.py | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/sos/archive.py b/sos/archive.py
index 6db398fc..4b30630b 100644
--- a/sos/archive.py
+++ b/sos/archive.py
@@ -439,8 +439,7 @@ class FileCacheArchive(Archive):
self.log_debug("No link follow up: source=%s link_name=%s" %
(source, link_name))
-
- def add_dir(self, path, copy=False):
+ def add_dir(self, path):
"""Create a directory in the archive.
:param path: the path in the host file system to add
--
2.26.0.windows.1

View File

@ -1,143 +0,0 @@
From 75d759066e8ee0a469abc37f48f7bfcdfe8182b5 Mon Sep 17 00:00:00 2001
From: "Bryn M. Reeves" <bmr@redhat.com>
Date: Fri, 31 Aug 2018 12:58:01 +0100
Subject: [PATCH 0026/1146] [archive] replace FileCacheArchive._makedirs()
The Python os.makedirs() implementation is inadequate for sos's
needs: it will create leading directories given an intended path
destination, but it is not able to reflect cases where some of
the intermediate paths are actually symbolic links.
Replace the use of os.makedirs() with a method that walks over
the path, and either creates directories, or symbolic links (and
their directory target) to better correspond with the content of
the host file system.
This fixes a situation where two plugins can race in the archive,
leading to an exception in the plugin that runs last:
- /foo/bar exists and is a link to /foo/bar.qux
- One plugin attempts to collect /foo/bar
- Another plugin attempts to collect a link /foo/qux -> /foo/bar/baz
If the 2nd plugin happens to run first it will create the path
"/foo/bar" as a _directory_ (via _makedirs()). Since the archive
now checks for matching object types when a path collision occurs,
the first plugin will arrive at add_dir(), note that "/foo/bar" is
present and is not a symbolic link, and will raise an exception.
Correct this by ensuring that whichever plugin executes first, the
correct link/directory path structure will be set up.
Signed-off-by: Bryn M. Reeves <bmr@redhat.com>
---
sos/archive.py | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 64 insertions(+), 8 deletions(-)
diff --git a/sos/archive.py b/sos/archive.py
index b7af508..473af86 100644
--- a/sos/archive.py
+++ b/sos/archive.py
@@ -158,6 +158,67 @@ class FileCacheArchive(Archive):
name = name.lstrip(os.sep)
return (os.path.join(self._archive_root, name))
+ def _make_leading_paths(self, src, mode=0o700):
+ """Create leading path components
+
+ The standard python `os.makedirs` is insufficient for our
+ needs: it will only create directories, and ignores the fact
+ that some path components may be symbolic links.
+ """
+ self.log_debug("Making leading paths for %s" % src)
+ root = self._archive_root
+
+ def in_archive(path):
+ """Test whether path ``path`` is inside the archive.
+ """
+ return path.startswith(os.path.join(root, ""))
+
+ if not src.startswith("/"):
+ # Sos archive path (sos_commands, sos_logs etc.)
+ src_dir = src
+ else:
+ # Host file path
+ src_dir = src if os.path.isdir(src) else os.path.split(src)[0]
+
+ # Build a list of path components in root-to-leaf order.
+ path = src_dir
+ path_comps = []
+ while path != '/' and path != '':
+ head, tail = os.path.split(path)
+ path_comps.append(tail)
+ path = head
+ path_comps.reverse()
+
+ abs_path = root
+ rel_path = ""
+
+ # Check and create components as needed
+ for comp in path_comps:
+ abs_path = os.path.join(abs_path, comp)
+
+ if not in_archive(abs_path):
+ continue
+
+ rel_path = os.path.join(rel_path, comp)
+ src_path = os.path.join("/", rel_path)
+
+ if not os.path.exists(abs_path):
+ self.log_debug("Making path %s" % abs_path)
+ if os.path.islink(src_path) and os.path.isdir(src_path):
+ target = os.readlink(src_path)
+ abs_target = os.path.join(root, target)
+
+ # Recursively create leading components of target
+ self._make_leading_paths(abs_target, mode=mode)
+
+ self.log_debug("Making symlink '%s' -> '%s'" %
+ (abs_path, target))
+ target = os.path.relpath(target)
+ os.symlink(target, abs_path)
+ else:
+ self.log_debug("Making directory %s" % abs_path)
+ os.mkdir(abs_path, mode)
+
def _check_path(self, src, path_type, dest=None):
"""Check a new destination path in the archive.
@@ -201,7 +262,8 @@ class FileCacheArchive(Archive):
raise ValueError("path '%s' exists and is not a directory" %
dest_dir)
elif not os.path.exists(dest_dir):
- self._makedirs(dest_dir)
+ src_dir = src if path_type == P_DIR else os.path.split(src)[0]
+ self._make_leading_paths(src_dir)
def is_special(mode):
return any([
@@ -319,10 +381,7 @@ class FileCacheArchive(Archive):
def add_dir(self, path):
with self._path_lock:
- dest = self._check_path(path, P_DIR)
- if not dest:
- return
- self.makedirs(path)
+ self._check_path(path, P_DIR)
def add_node(self, path, mode, device):
dest = self._check_path(path, P_NODE)
@@ -340,9 +399,6 @@ class FileCacheArchive(Archive):
raise e
shutil.copystat(path, dest)
- def _makedirs(self, path, mode=0o700):
- os.makedirs(path, mode)
-
def name_max(self):
if 'PC_NAME_MAX' in os.pathconf_names:
pc_name_max = os.pathconf_names['PC_NAME_MAX']
--
2.13.7

View File

@ -1,42 +0,0 @@
From c496d2bec8cae175faf986567e73d16d401d8564 Mon Sep 17 00:00:00 2001
From: "Bryn M. Reeves" <bmr@redhat.com>
Date: Fri, 31 Aug 2018 12:52:38 +0100
Subject: [PATCH 0024/1146] [archive] simplify FileCacheArchive.makedirs()
Simplify the makedirs() method of FileCacheArchive and have it
bypass _check_path() and directly call os.makedirs(): a subsequent
patch will restrict the use of the method to setting up the sos_*
directories in the archive root.
File, directory and other object type add_* methods will use a
new method that correctly handles symbolic links in intermediate
path components.
Signed-off-by: Bryn M. Reeves <bmr@redhat.com>
---
sos/archive.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/sos/archive.py b/sos/archive.py
index 5d99170f..ffa54036 100644
--- a/sos/archive.py
+++ b/sos/archive.py
@@ -361,11 +361,11 @@ class FileCacheArchive(Archive):
return self._archive_root
def makedirs(self, path, mode=0o700):
- dest = self._check_path(path, P_DIR)
- if not dest:
- return
+ """Create path, including leading components.
- self._makedirs(self.dest_path(path))
+ Used by sos.sosreport to set up sos_* directories.
+ """
+ os.makedirs(os.path.join(self._archive_root, path), mode=mode)
self.log_debug("created directory at '%s' in FileCacheArchive '%s'"
% (path, self._archive_root))
--
2.26.0.windows.1

View File

@ -1,52 +0,0 @@
From bc650cd161548159e551ddc201596bf19b1865d0 Mon Sep 17 00:00:00 2001
From: Pavel Moravec <pmoravec@redhat.com>
Date: Fri, 27 Jul 2018 08:56:37 +0200
Subject: [PATCH 0012/1146] [policies] sanitize report label
similarly like we sanitize case id, we should sanitize report label
to e.g. exclude spaces from final tarball name.
Resolves: #1389
Signed-off-by: Pavel Moravec <pmoravec@redhat.com>
---
sos/policies/__init__.py | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/sos/policies/__init__.py b/sos/policies/__init__.py
index 7b301dec..65d8aac6 100644
--- a/sos/policies/__init__.py
+++ b/sos/policies/__init__.py
@@ -408,7 +408,7 @@ No changes will be made to system configuration.
date=date,
rand=rand
)
- return time.strftime(nstr)
+ return self.sanitize_filename(time.strftime(nstr))
# for some specific binaries like "xz", we need to determine package
# providing it; that is policy specific. By default return the binary
@@ -726,8 +726,8 @@ class LinuxPolicy(Policy):
"""Returns the name usd in the pre_work step"""
return self.host_name()
- def sanitize_case_id(self, case_id):
- return re.sub(r"[^-a-z,A-Z.0-9]", "", case_id)
+ def sanitize_filename(self, name):
+ return re.sub(r"[^-a-z,A-Z.0-9]", "", name)
def lsmod(self):
"""Return a list of kernel module names as strings.
@@ -755,9 +755,6 @@ class LinuxPolicy(Policy):
if cmdline_opts.case_id:
self.case_id = cmdline_opts.case_id
- if self.case_id:
- self.case_id = self.sanitize_case_id(self.case_id)
-
return
--
2.26.0.windows.1

View File

@ -1,34 +0,0 @@
From d6379b5ba0f381ea8ec2403b9985100a946a5866 Mon Sep 17 00:00:00 2001
From: Pavel Moravec <pmoravec@redhat.com>
Date: Mon, 8 Oct 2018 10:45:04 +0200
Subject: [PATCH 60/87] [kernel] dont collect some tracing instance files
reason: dont collect some tracing instance files
https://github.com/sosreport/sos/pull/1445/files
Resolves: #1445
Signed-off-by: Pavel Moravec <pmoravec@redhat.com>
---
sos/plugins/kernel.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/sos/plugins/kernel.py b/sos/plugins/kernel.py
index 7310932..558e714 100644
--- a/sos/plugins/kernel.py
+++ b/sos/plugins/kernel.py
@@ -93,7 +93,10 @@ class Kernel(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
'/sys/kernel/debug/tracing/events/*',
'/sys/kernel/debug/tracing/free_buffer',
'/sys/kernel/debug/tracing/trace_marker',
- '/sys/kernel/debug/tracing/trace_marker_raw'
+ '/sys/kernel/debug/tracing/trace_marker_raw',
+ '/sys/kernel/debug/tracing/instances/*/per_cpu/*/snapshot_raw',
+ '/sys/kernel/debug/tracing/instances/*/per_cpu/*/trace_pipe*',
+ '/sys/kernel/debug/tracing/instances/*/trace_pipe'
])
self.add_copy_spec([
--
1.8.3.1

View File

@ -3,21 +3,21 @@ From: shixuantong <shixuantong@huawei.com>
Date: Mon, 8 Mar 2021 20:56:05 +0800
Subject: [PATCH] add openEuler policy
this patch is based on sos-3.6.
this patch is based on sos-3.8.
---
sos/policies/openEuler.py | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
sos/policies/openEuler.py | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
create mode 100644 sos/policies/openEuler.py
diff --git a/sos/policies/openEuler.py b/sos/policies/openEuler.py
new file mode 100644
index 0000000..0c9b8f3
index 0000000..ea65ba2
--- /dev/null
+++ b/sos/policies/openEuler.py
@@ -0,0 +1,29 @@
@@ -0,0 +1,30 @@
+from __future__ import print_function
+
+from sos.plugins import RedHatPlugin
+from sos.report.plugins import RedHatPlugin
+from sos.policies.redhat import RedHatPolicy, OS_RELEASE
+import os
+
@ -27,19 +27,20 @@ index 0000000..0c9b8f3
+ vendor = "the openEuler Project"
+ vendor_url = "https://openeuler.org/"
+
+ def __init__(self, sysroot=None):
+ super(OpenEulerPolicy, self).__init__(sysroot=sysroot)
+ def __init__(self, sysroot=None, init=None, probe_runtime=True,
+ remote_exec=None):
+ super(OpenEulerPolicy, self).__init__(sysroot=sysroot, init=init,
+ probe_runtime=probe_runtime,
+ remote_exec=remote_exec)
+
+ @classmethod
+ def check(cls):
+ def check(cls, remote=''):
+ """This method checks to see if we are running on OpenEuler. It returns
+ True or False."""
+ try:
+ with open("/etc/openEuler-release", "r") as f:
+ return "openEuler" in f.read()
+ except IOError:
+ return False
+
+ if remote:
+ return cls.distro in remote
+ return os.path.isfile('/etc/openEuler-release')
+
+ def openEuler_version(self):
+ pkg = self.pkg_by_name("openEuler-release") or \
+ self.all_pkgs_by_name_regex("openEuler-release-.*")[-1]

BIN
sos-3.8.tar.gz Normal file

Binary file not shown.

View File

@ -1,32 +1,20 @@
%{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
Name: sos
Version: 3.6
Release: 6
Version: 3.8
Release: 1
Summary: A set of tools to gather troubleshooting information from a system
License: GPLv2+
URL: http://github.com/sosreport/sos
Source0: https://github.com/sosreport/sos/archive/%{version}.tar.gz
URL: https://github.com/sosreport/sos
Source0: https://github.com/sosreport/sos/archive/%{version}/%{name}-%{version}.tar.gz
Patch9000: openEuler-add-openEuler-policy.patch
Patch9001: add-uniontech-os-support.patch
BuildRequires: python3-devel gettext python3-six
Requires: libxml2-python3 bzip2 xz python3-six
Requires: libxml2-python3 xz python3-rpm tar bzip2 python3-six
BuildArch: noarch
Patch0: kernel-dont-collect-some-tracing-instance-files.patch
Patch6000: backport-policies-sanitize-report-label.patch
Patch6001: backport-archive-Dont-copystat-sys-and-proc-paths.patch
Patch6002: backport-archive-simplify-FileCacheArchive.makedirs.patch
Patch6003: backport-archive-normalise-dest_dir-in-FileCacheArchive._chec.patch
Patch6004: backport-archive-replace-FileCacheArchive._makedirs.patch
Patch6005: backport-Policies-Plugins-Add-services-member.patch
Patch6006: backport-Plugin-fix-exception-raise-in-Plugin._copy_dir.patch
Patch6007: backport-archive-fix-leading-path-creation.patch
Patch6008: backport-archive-add-link-follow-up-to-FileCacheArchive.add_l.patch
Patch6009: backport-archive-remove-unused-copy-arg-from-FileCacheArchive.patch
Patch6010: backport-archive-fix-local-variable-name-in-FileCacheArchive.patch
Patch9000: openEuler-add-openEuler-policy.patch
%description
Sos is an extensible, portable, support data collection tool primarily
aimed at Linux distributions and other UNIX-like operating systems.
@ -41,24 +29,27 @@ aimed at Linux distributions and other UNIX-like operating systems.
%install
%py3_install '--install-scripts=%{_sbindir}'
install -Dm644 %{name}.conf %{buildroot}%{_sysconfdir}/%{name}.conf
%find_lang %{name} || echo 0
%files -f %{name}.lang
%license LICENSE
%defattr(-,root,root)
%config(noreplace) %{_sysconfdir}/sos.conf
%{_sbindir}/sosreport
%{python3_sitelib}/*
%license LICENSE
%config(noreplace) %{_sysconfdir}/sos.conf
%files help
%defattr(-,root,root)
%doc AUTHORS README.md
%{_mandir}/man1/sosreport.1.gz
%{_mandir}/man5/sos.conf.5.gz
%{_mandir}/man1/*
%{_mandir}/man5/*
%changelog
* Tue Sep 14 2021 baizhonggui <baizhonggui@huawei.com> - 3.8-1
- Update to 3.8
* Tue May 11 2021 shixuantong <shixuantong@huawei.com> - 3.6-6
- add openEuler policy and fix exception in plugin method "yum.collect()"

4
sos.yaml Normal file
View File

@ -0,0 +1,4 @@
version_control: github
src_repo: sosreport/sos
tag_prefix: ^v
seperator: .