add openEuler policy and fix exception in plugin method "yum.collect()"
This commit is contained in:
parent
bc9d333edc
commit
710d6ef295
@ -0,0 +1,30 @@
|
||||
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
|
||||
|
||||
284
backport-Policies-Plugins-Add-services-member.patch
Normal file
284
backport-Policies-Plugins-Add-services-member.patch
Normal file
@ -0,0 +1,284 @@
|
||||
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
|
||||
|
||||
46
backport-archive-Dont-copystat-sys-and-proc-paths.patch
Normal file
46
backport-archive-Dont-copystat-sys-and-proc-paths.patch
Normal file
@ -0,0 +1,46 @@
|
||||
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
|
||||
|
||||
@ -0,0 +1,85 @@
|
||||
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
|
||||
|
||||
122
backport-archive-fix-leading-path-creation.patch
Normal file
122
backport-archive-fix-leading-path-creation.patch
Normal file
@ -0,0 +1,122 @@
|
||||
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
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
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
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
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
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
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
|
||||
|
||||
143
backport-archive-replace-FileCacheArchive._makedirs.patch
Normal file
143
backport-archive-replace-FileCacheArchive._makedirs.patch
Normal file
@ -0,0 +1,143 @@
|
||||
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
|
||||
|
||||
42
backport-archive-simplify-FileCacheArchive.makedirs.patch
Normal file
42
backport-archive-simplify-FileCacheArchive.makedirs.patch
Normal file
@ -0,0 +1,42 @@
|
||||
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
|
||||
|
||||
52
backport-policies-sanitize-report-label.patch
Normal file
52
backport-policies-sanitize-report-label.patch
Normal file
@ -0,0 +1,52 @@
|
||||
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
|
||||
|
||||
49
openEuler-add-openEuler-policy.patch
Normal file
49
openEuler-add-openEuler-policy.patch
Normal file
@ -0,0 +1,49 @@
|
||||
From 3b76979a51f8b8e65991c00cd4ebab2f23a467a6 Mon Sep 17 00:00:00 2001
|
||||
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.
|
||||
---
|
||||
sos/policies/openEuler.py | 29 +++++++++++++++++++++++++++++
|
||||
1 file changed, 29 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
|
||||
--- /dev/null
|
||||
+++ b/sos/policies/openEuler.py
|
||||
@@ -0,0 +1,29 @@
|
||||
+from __future__ import print_function
|
||||
+
|
||||
+from sos.plugins import RedHatPlugin
|
||||
+from sos.policies.redhat import RedHatPolicy, OS_RELEASE
|
||||
+import os
|
||||
+
|
||||
+class OpenEulerPolicy(RedHatPolicy):
|
||||
+
|
||||
+ distro = "OpenEuler"
|
||||
+ vendor = "the openEuler Project"
|
||||
+ vendor_url = "https://openeuler.org/"
|
||||
+
|
||||
+ def __init__(self, sysroot=None):
|
||||
+ super(OpenEulerPolicy, self).__init__(sysroot=sysroot)
|
||||
+
|
||||
+ @classmethod
|
||||
+ def check(cls):
|
||||
+ """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
|
||||
+
|
||||
+ def openEuler_version(self):
|
||||
+ pkg = self.pkg_by_name("openEuler-release") or \
|
||||
+ self.all_pkgs_by_name_regex("openEuler-release-.*")[-1]
|
||||
+ return int(pkg["version"])
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
18
sos.spec
18
sos.spec
@ -2,7 +2,7 @@
|
||||
|
||||
Name: sos
|
||||
Version: 3.6
|
||||
Release: 5
|
||||
Release: 6
|
||||
Summary: A set of tools to gather troubleshooting information from a system
|
||||
License: GPLv2+
|
||||
URL: http://github.com/sosreport/sos
|
||||
@ -13,6 +13,19 @@ Requires: libxml2-python3 bzip2 xz 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
|
||||
@ -46,5 +59,8 @@ install -Dm644 %{name}.conf %{buildroot}%{_sysconfdir}/%{name}.conf
|
||||
%{_mandir}/man5/sos.conf.5.gz
|
||||
|
||||
%changelog
|
||||
* Tue May 11 2021 shixuantong <shixuantong@huawei.com> - 3.6-6
|
||||
- add openEuler policy and fix exception in plugin method "yum.collect()"
|
||||
|
||||
* Mon Feb 17 2020 openEuler Buildteam <buildteam@openeuler.org> - 3.6-5
|
||||
- Package init
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user