sosreport-3.2+git276-g7da50d6/ 0000755 0001750 0001750 00000000000 12625313241 015504 5 ustar caribou caribou sosreport-3.2+git276-g7da50d6/example_plugins/ 0000755 0001750 0001750 00000000000 12625313241 020700 5 ustar caribou caribou sosreport-3.2+git276-g7da50d6/example_plugins/example.py 0000755 0001750 0001750 00000005224 12625313241 022713 0 ustar caribou caribou ### This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin
# the class name determines the plugin name
# if you want to override it simply provide a @classmethod name()
# that returns the name you want
class example(Plugin, RedHatPlugin):
'''This is the description for the example plugin'''
# Plugin developers want to override setup() from which they will call
# add_copy_spec() to collect files and collectExtOutput() to collect programs
# output.
# Add your options here, indicate whether they are slow to run, and set
# whether they are enabled by default
# each option is a tuple of the following format:
# (name, description, fast or slow, default value)
# each option will be addressable like -k name=value
option_list = [("init.d", 'Gathers the init.d directory', 'slow', 0),
('follicles', 'Gathers information about each follicle on every toe', 'slow', 0),
('color', 'Gathers toenail polish color', 'fast', 0)]
def setup(self):
''' First phase - Collect all the information we need.
Directories are copied recursively. arbitrary commands may be
executed using the collectExtOutput() method. Information is
automatically saved, and links are presented in the report to each
file or directory which has been copied to the saved tree. Also, links
are provided to the output from each command.
'''
# Here's how to copy files and directory trees
self.add_copy_spec("/etc/hosts")
with open("/proc/cpuinfo") as f:
for line in f:
if "vendor_id" in line:
self.add_alert("Vendor ID string is: %s
\n" % line)
# Here's how to test your options and execute if enabled
if self.option_enabled("init.d"):
self.add_copy_spec("/etc/init.d") # copies a whole directory tree
# Here's how to execute a command
self.collectExtOutput("/bin/ps -ef")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/ 0000755 0001750 0001750 00000000000 12625313247 016316 5 ustar caribou caribou sosreport-3.2+git276-g7da50d6/sos/archive.py 0000644 0001750 0001750 00000033730 12625313247 020317 0 ustar caribou caribou # Copyright (C) 2012 Red Hat, Inc.,
# Jesse Jaggars
# Bryn M. Reeves
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
import os
import time
import tarfile
import shutil
import logging
import shlex
import re
import codecs
import sys
# required for compression callout (FIXME: move to policy?)
from subprocess import Popen, PIPE
try:
import selinux
except ImportError:
pass
# PYCOMPAT
import six
if six.PY3:
long = int
class Archive(object):
"""Abstract base class for archives."""
@classmethod
def archive_type(class_):
"""Returns the archive class's name as a string.
"""
return class_.__name__
log = logging.getLogger("sos")
_name = "unset"
_debug = False
def _format_msg(self, msg):
return "[archive:%s] %s" % (self.archive_type(), msg)
def set_debug(self, debug):
self._debug = debug
def log_error(self, msg):
self.log.error(self._format_msg(msg))
def log_warn(self, msg):
self.log.warning(self._format_msg(msg))
def log_info(self, msg):
self.log.info(self._format_msg(msg))
def log_debug(self, msg):
if not self._debug:
return
self.log.debug(self._format_msg(msg))
# this is our contract to clients of the Archive class hierarchy.
# All sub-classes need to implement these methods (or inherit concrete
# implementations from a parent class.
def add_file(self, src, dest=None):
raise NotImplementedError
def add_string(self, content, dest):
raise NotImplementedError
def add_link(self, source, link_name):
raise NotImplementedError
def add_dir(self, path):
raise NotImplementedError
def add_node(self, path, mode, device):
raise NotImplementedError
def get_tmp_dir(self):
"""Return a temporary directory that clients of the archive may
use to write content to. The content of the path is guaranteed
to be included in the generated archive."""
raise NotImplementedError
def name_max(self):
"""Return the maximum file name length this archive can support.
This is the lesser of the name length limit of the archive
format and any temporary file system based cache."""
raise NotImplementedError
def get_archive_path(self):
"""Return a string representing the path to the temporary
archive. For archive classes that implement in-line handling
this will be the archive file itself. Archives that use a
directory based cache prior to packaging should return the
path to the temporary directory where the report content is
located"""
pass
def cleanup(self):
"""Clean up any temporary resources used by an Archive class."""
pass
def finalize(self, method):
"""Finalize an archive object via method. This may involve creating
An archive that is subsequently compressed or simply closing an
archive that supports in-line handling. If method is automatic then
the following methods are tried in order: xz, bz2 and gzip"""
self.close()
class FileCacheArchive(Archive):
""" Abstract superclass for archive types that use a temporary cache
directory in the file system. """
_tmp_dir = ""
_archive_root = ""
_archive_name = ""
def __init__(self, name, tmpdir):
self._name = name
self._tmp_dir = tmpdir
self._archive_root = os.path.join(tmpdir, name)
os.makedirs(self._archive_root, 0o700)
self.log_info("initialised empty FileCacheArchive at '%s'" %
(self._archive_root,))
def dest_path(self, name):
if os.path.isabs(name):
name = name.lstrip(os.sep)
return (os.path.join(self._archive_root, name))
def _check_path(self, dest):
dest_dir = os.path.split(dest)[0]
if not dest_dir:
return
if not os.path.isdir(dest_dir):
self._makedirs(dest_dir)
def add_file(self, src, dest=None):
if not dest:
dest = src
dest = self.dest_path(dest)
self._check_path(dest)
try:
shutil.copy(src, dest)
except IOError as e:
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
try:
stat = os.stat(src)
os.chown(dest, stat.st_uid, stat.st_gid)
except Exception as e:
self.log_debug("caught '%s' setting ownership of '%s'" % (e, dest))
self.log_debug("added '%s' to FileCacheArchive '%s'" %
(src, self._archive_root))
def add_string(self, content, dest):
src = dest
dest = self.dest_path(dest)
self._check_path(dest)
f = codecs.open(dest, 'w', encoding='utf-8')
if isinstance(content, bytes):
content = content.decode('utf8', 'ignore')
f.write(content)
if os.path.exists(src):
try:
shutil.copystat(src, dest)
except OSError as e:
self.log_error(
"Unable to add '%s' to FileCacheArchive: %s" % (dest, e))
self.log_debug("added string at '%s' to FileCacheArchive '%s'"
% (src, self._archive_root))
def add_link(self, source, link_name):
dest = self.dest_path(link_name)
self._check_path(dest)
if not os.path.lexists(dest):
os.symlink(source, dest)
self.log_debug("added symlink at '%s' to '%s' in FileCacheArchive '%s'"
% (dest, source, self._archive_root))
def add_dir(self, path):
self.makedirs(path)
def add_node(self, path, mode, device):
dest = self.dest_path(path)
self._check_path(dest)
if not os.path.exists(dest):
os.mknod(dest, mode, device)
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']
return os.pathconf(self._archive_root, pc_name_max)
else:
return 255
def get_tmp_dir(self):
return self._archive_root
def get_archive_path(self):
return self._archive_root
def makedirs(self, path, mode=0o700):
self._makedirs(self.dest_path(path))
self.log_debug("created directory at '%s' in FileCacheArchive '%s'"
% (path, self._archive_root))
def open_file(self, path):
path = self.dest_path(path)
return codecs.open(path, "r", encoding='utf-8')
def cleanup(self):
shutil.rmtree(self._archive_root)
def finalize(self, method):
self.log_info("finalizing archive '%s' using method '%s'"
% (self._archive_root, method))
self._build_archive()
self.cleanup()
self.log_info("built archive at '%s' (size=%d)" % (self._archive_name,
os.stat(self._archive_name).st_size))
self.method = method
return self._compress()
# Compatibility version of the tarfile.TarFile class. This exists to allow
# compatibility with PY2 runtimes that lack the 'filter' parameter to the
# TarFile.add() method. The wrapper class is used on python2.6 and earlier
# only; all later versions include 'filter' and the native TarFile class is
# used directly.
class _TarFile(tarfile.TarFile):
# Taken from the python 2.7.5 tarfile.py
def add(self, name, arcname=None, recursive=True,
exclude=None, filter=None):
"""Add the file `name' to the archive. `name' may be any type of file
(directory, fifo, symbolic link, etc.). If given, `arcname'
specifies an alternative name for the file in the archive.
Directories are added recursively by default. This can be avoided by
setting `recursive' to False. `exclude' is a function that should
return True for each filename to be excluded. `filter' is a function
that expects a TarInfo object argument and returns the changed
TarInfo object, if it returns None the TarInfo object will be
excluded from the archive.
"""
self._check("aw")
if arcname is None:
arcname = name
# Exclude pathnames.
if exclude is not None:
import warnings
warnings.warn("use the filter argument instead",
DeprecationWarning, 2)
if exclude(name):
self._dbg(2, "tarfile: Excluded %r" % name)
return
# Skip if somebody tries to archive the archive...
if self.name is not None and os.path.abspath(name) == self.name:
self._dbg(2, "tarfile: Skipped %r" % name)
return
self._dbg(1, name)
# Create a TarInfo object from the file.
tarinfo = self.gettarinfo(name, arcname)
if tarinfo is None:
self._dbg(1, "tarfile: Unsupported type %r" % name)
return
# Change or exclude the TarInfo object.
if filter is not None:
tarinfo = filter(tarinfo)
if tarinfo is None:
self._dbg(2, "tarfile: Excluded %r" % name)
return
# Append the tar header and data to the archive.
if tarinfo.isreg():
with tarfile.bltn_open(name, "rb") as f:
self.addfile(tarinfo, f)
elif tarinfo.isdir():
self.addfile(tarinfo)
if recursive:
for f in os.listdir(name):
self.add(os.path.join(name, f), os.path.join(arcname, f),
recursive, exclude, filter)
else:
self.addfile(tarinfo)
class TarFileArchive(FileCacheArchive):
""" archive class using python TarFile to create tar archives"""
method = None
_with_selinux_context = False
def __init__(self, name, tmpdir):
super(TarFileArchive, self).__init__(name, tmpdir)
self._suffix = "tar"
self._archive_name = os.path.join(tmpdir, self.name())
def set_tarinfo_from_stat(self, tar_info, fstat, mode=None):
tar_info.mtime = fstat.st_mtime
tar_info.pax_headers['atime'] = "%.9f" % fstat.st_atime
tar_info.pax_headers['ctime'] = "%.9f" % fstat.st_ctime
if mode:
tar_info.mode = mode
else:
tar_info.mode = fstat.st_mode
tar_info.uid = fstat.st_uid
tar_info.gid = fstat.st_gid
# this can be used to set permissions if using the
# tarfile.add() interface to add directory trees.
def copy_permissions_filter(self, tarinfo):
orig_path = tarinfo.name[len(os.path.split(self._name)[-1]):]
if not orig_path:
orig_path = self._archive_root
try:
fstat = os.stat(orig_path)
except OSError:
return tarinfo
if self._with_selinux_context:
context = self.get_selinux_context(orig_path)
if(context):
tarinfo.pax_headers['RHT.security.selinux'] = context
self.set_tarinfo_from_stat(tarinfo, fstat)
return tarinfo
def get_selinux_context(self, path):
try:
(rc, c) = selinux.getfilecon(path)
return c
except:
return None
def name(self):
return "%s.%s" % (self._name, self._suffix)
def name_max(self):
# GNU Tar format supports unlimited file name length. Just return
# the limit of the underlying FileCacheArchive.
return super(TarFileArchive, self).name_max()
def _build_archive(self):
# python2.6 TarFile lacks the filter parameter
if not six.PY3 and sys.version_info[1] < 7:
tar = _TarFile.open(self._archive_name, mode="w")
else:
tar = tarfile.open(self._archive_name, mode="w")
# we need to pass the absolute path to the archive root but we
# want the names used in the archive to be relative.
tar.add(self._archive_root, arcname=os.path.split(self._name)[1],
filter=self.copy_permissions_filter)
tar.close()
def _compress(self):
methods = ['xz', 'bzip2', 'gzip']
if self.method in methods:
methods = [self.method]
last_error = Exception("compression failed for an unknown reason")
for cmd in methods:
suffix = "." + cmd.replace('ip', '')
# use fast compression if using xz or bz2
if cmd != "gzip":
cmd = "%s -1" % cmd
try:
command = shlex.split("%s %s" % (cmd, self.name()))
p = Popen(command,
stdout=PIPE,
stderr=PIPE,
bufsize=-1,
close_fds=True)
stdout, stderr = p.communicate()
if stdout:
self.log_info(stdout.decode('utf-8', 'ignore'))
if stderr:
self.log_error(stderr.decode('utf-8', 'ignore'))
self._suffix += suffix
return self.name()
except Exception as e:
last_error = e
raise last_error
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/utilities.py 0000644 0001750 0001750 00000017243 12625313241 020704 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from __future__ import with_statement
import os
import re
import inspect
from subprocess import Popen, PIPE, STDOUT
import hashlib
import logging
import fnmatch
import errno
import shlex
from contextlib import closing
# PYCOMPAT
import six
from six import StringIO
def tail(filename, number_of_bytes):
"""Returns the last number_of_bytes of filename"""
with open(filename, "rb") as f:
if os.stat(filename).st_size > number_of_bytes:
f.seek(-number_of_bytes, 2)
return f.read()
def fileobj(path_or_file, mode='r'):
"""Returns a file-like object that can be used as a context manager"""
if isinstance(path_or_file, six.string_types):
try:
return open(path_or_file, mode)
except:
log = logging.getLogger('sos')
log.debug("fileobj: %s could not be opened" % path_or_file)
return closing(StringIO())
else:
return closing(path_or_file)
def get_hash_name():
"""Returns the algorithm used when computing a hash"""
import sos.policies
policy = sos.policies.load()
try:
name = policy.get_preferred_hash_algorithm()
hashlib.new(name)
return name
except:
return 'sha256'
def convert_bytes(bytes_, K=1 << 10, M=1 << 20, G=1 << 30, T=1 << 40):
"""Converts a number of bytes to a shorter, more human friendly format"""
fn = float(bytes_)
if bytes_ >= T:
return '%.1fT' % (fn / T)
elif bytes_ >= G:
return '%.1fG' % (fn / G)
elif bytes_ >= M:
return '%.1fM' % (fn / M)
elif bytes_ >= K:
return '%.1fK' % (fn / K)
else:
return '%d' % bytes_
def find(file_pattern, top_dir, max_depth=None, path_pattern=None):
"""generator function to find files recursively. Usage:
for filename in find("*.properties", "/var/log/foobar"):
print filename
"""
if max_depth:
base_depth = os.path.dirname(top_dir).count(os.path.sep)
max_depth += base_depth
for path, dirlist, filelist in os.walk(top_dir):
if max_depth and path.count(os.path.sep) >= max_depth:
del dirlist[:]
if path_pattern and not fnmatch.fnmatch(path, path_pattern):
continue
for name in fnmatch.filter(filelist, file_pattern):
yield os.path.join(path, name)
def grep(pattern, *files_or_paths):
"""Returns lines matched in fnames, where fnames can either be pathnames to
files to grep through or open file objects to grep through line by line"""
matches = []
for fop in files_or_paths:
with fileobj(fop) as fo:
matches.extend((line for line in fo if re.match(pattern, line)))
return matches
def is_executable(command):
"""Returns if a command matches an executable on the PATH"""
paths = os.environ.get("PATH", "").split(os.path.pathsep)
candidates = [command] + [os.path.join(p, command) for p in paths]
return any(os.access(path, os.X_OK) for path in candidates)
def sos_get_command_output(command, timeout=300, stderr=False,
chroot=None, chdir=None):
"""Execute a command and return a dictionary of status and output,
optionally changing root or current working directory before
executing command.
"""
# Change root or cwd for child only. Exceptions in the prexec_fn
# closure are caught in the parent (chroot and chdir are bound from
# the enclosing scope).
def _child_prep_fn():
if (chroot):
os.chroot(chroot)
if (chdir):
os.chdir(chdir)
cmd_env = os.environ
# ensure consistent locale for collected command output
cmd_env['LC_ALL'] = 'C'
# use /usr/bin/timeout to implement a timeout
if timeout and is_executable("timeout"):
command = "timeout %ds %s" % (timeout, command)
# shlex.split() reacts badly to unicode on older python runtimes.
if not six.PY3:
command = command.encode('utf-8', 'ignore')
args = shlex.split(command)
try:
p = Popen(args, shell=False, stdout=PIPE,
stderr=STDOUT if stderr else PIPE,
bufsize=-1, env=cmd_env, close_fds=True,
preexec_fn=_child_prep_fn)
stdout, stderr = p.communicate()
except OSError as e:
if e.errno == errno.ENOENT:
return {'status': 127, 'output': ""}
else:
raise e
if p.returncode == 126 or p.returncode == 127:
stdout = six.binary_type(b"")
return {
'status': p.returncode,
'output': stdout.decode('utf-8', 'ignore')
}
def import_module(module_fqname, superclasses=None):
"""Imports the module module_fqname and returns a list of defined classes
from that module. If superclasses is defined then the classes returned will
be subclasses of the specified superclass or superclasses. If superclasses
is plural it must be a tuple of classes."""
module_name = module_fqname.rpartition(".")[-1]
module = __import__(module_fqname, globals(), locals(), [module_name])
modules = [class_ for cname, class_ in
inspect.getmembers(module, inspect.isclass)
if class_.__module__ == module_fqname]
if superclasses:
modules = [m for m in modules if issubclass(m, superclasses)]
return modules
def shell_out(cmd, timeout=30, chroot=None, runat=None):
"""Shell out to an external command and return the output or the empty
string in case of error.
"""
return sos_get_command_output(cmd, timeout=timeout,
chroot=chroot, chdir=runat)['output']
class ImporterHelper(object):
"""Provides a list of modules that can be imported in a package.
Importable modules are located along the module __path__ list and modules
are files that end in .py.
"""
def __init__(self, package):
"""package is a package module
import my.package.module
helper = ImporterHelper(my.package.module)"""
self.package = package
def _plugin_name(self, path):
"Returns the plugin module name given the path"
base = os.path.basename(path)
name, ext = os.path.splitext(base)
return name
def _get_plugins_from_list(self, list_):
plugins = [self._plugin_name(plugin)
for plugin in list_
if "__init__" not in plugin and plugin.endswith(".py")]
plugins.sort()
return plugins
def _find_plugins_in_dir(self, path):
if os.path.exists(path):
py_files = list(find("*.py", path))
pnames = self._get_plugins_from_list(py_files)
if pnames:
return pnames
else:
return []
def get_modules(self):
"""Returns the list of importable modules in the configured python
package. """
plugins = []
for path in self.package.__path__:
if os.path.isdir(path) or path == '':
plugins.extend(self._find_plugins_in_dir(path))
return plugins
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/policies/ 0000755 0001750 0001750 00000000000 12625313241 020117 5 ustar caribou caribou sosreport-3.2+git276-g7da50d6/sos/policies/osx.py 0000644 0001750 0001750 00000000462 12625313241 021304 0 ustar caribou caribou from sos.policies import Policy
from sos.utilities import shell_out
class OSXPolicy(Policy):
distro = "Mac OS X"
@classmethod
def check(class_):
try:
return "Mac OS X" in shell_out("sw_vers")
except Exception:
return False
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/policies/redhat.py 0000644 0001750 0001750 00000020156 12625313241 021744 0 ustar caribou caribou # Copyright (C) Steve Conklin
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# This enables the use of with syntax in python 2.5 (e.g. jython)
from __future__ import print_function
import os
import sys
from sos.plugins import RedHatPlugin
from sos.policies import LinuxPolicy, PackageManager
from sos import _sos as _
sys.path.insert(0, "/usr/share/rhn/")
try:
from up2date_client import up2dateAuth
from up2date_client import config
from rhn import rpclib
except:
# might fail if non-RHEL
pass
class RedHatPolicy(LinuxPolicy):
distro = "Red Hat"
vendor = "Red Hat"
vendor_url = "http://www.redhat.com/"
_redhat_release = '/etc/redhat-release'
_tmp_dir = "/var/tmp"
_rpmq_cmd = 'rpm -qa --queryformat "%{NAME}|%{VERSION}\\n"'
_in_container = False
_host_sysroot = '/'
def __init__(self, sysroot=None):
super(RedHatPolicy, self).__init__(sysroot=sysroot)
self.report_name = ""
self.ticket_number = ""
# need to set _host_sysroot before PackageManager()
if sysroot:
self._container_init()
self._host_sysroot = sysroot
else:
sysroot = self._container_init()
self.package_manager = PackageManager(self._rpmq_cmd, chroot=sysroot)
self.valid_subclasses = [RedHatPlugin]
pkgs = self.package_manager.all_pkgs()
# If rpm query timed out after timeout duration exit
if not pkgs:
print("Could not obtain installed package list", file=sys.stderr)
sys.exit(1)
# handle PATH for UsrMove
if pkgs['filesystem']['version'][0] == '3':
self.PATH = "/usr/sbin:/usr/bin:/root/bin"
else:
self.PATH = "/sbin:/bin:/usr/sbin:/usr/bin:/root/bin"
self.PATH += os.pathsep + "/usr/local/bin"
self.PATH += os.pathsep + "/usr/local/sbin"
self.set_exec_path()
@classmethod
def check(self):
"""This method checks to see if we are running on Red Hat. It must be
overriden by concrete subclasses to return True when running on a
Fedora, RHEL or other Red Hat distribution or False otherwise."""
return False
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_UUID in os.environ:
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:
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 Red Hat systems.
ENV_CONTAINER_UUID = 'container_uuid'
ENV_HOST_SYSROOT = 'HOST'
class RHELPolicy(RedHatPolicy):
distro = "Red Hat Enterprise Linux"
vendor = "Red Hat"
vendor_url = "https://access.redhat.com/support/"
msg = _("""\
This command will collect diagnostic and configuration \
information from this %(distro)s system and installed \
applications.
An archive containing the collected information will be \
generated in %(tmpdir)s and may be provided to a %(vendor)s \
support representative.
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.
%(vendor_text)s
""")
def __init__(self, sysroot=None):
super(RHELPolicy, self).__init__(sysroot=sysroot)
@classmethod
def check(self):
"""This method checks to see if we are running on RHEL. It returns True
or False."""
return (os.path.isfile(self._redhat_release) and not
os.path.isfile('/etc/fedora-release'))
def dist_version(self):
try:
pkg = self.pkg_by_name("redhat-release") or \
self.all_pkgs_by_name_regex("redhat-release-.*")[-1]
pkgname = pkg["version"]
if pkgname[0] == "4":
return 4
elif pkgname[0] in ["5Server", "5Client"]:
return 5
elif pkgname[0] == "6":
return 6
elif pkgname[0] == "7":
return 7
except:
pass
return False
def rhn_username(self):
try:
# cfg = config.initUp2dateConfig()
return rpclib.xmlrpclib.loads(
up2dateAuth.getSystemId())[0][0]['username']
except:
# ignore any exception and return an empty username
return ""
def get_local_name(self):
return self.rhn_username() or self.host_name()
class RedHatAtomicPolicy(RHELPolicy):
distro = "Red Hat Atomic Host"
msg = _("""\
This command will collect diagnostic and configuration \
information from this %(distro)s system.
An archive containing the collected information will be \
generated in %(tmpdir)s and may be provided to a %(vendor)s \
support representative.
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.
%(vendor_text)s
""")
@classmethod
def check(self):
atomic = False
if ENV_HOST_SYSROOT not in os.environ:
return atomic
host_release = os.environ[ENV_HOST_SYSROOT] + self._redhat_release
if not os.path.exists(host_release):
return False
try:
for line in open(host_release, "r").read().splitlines():
atomic |= 'Atomic' in line
except:
pass
return atomic
class FedoraPolicy(RedHatPolicy):
distro = "Fedora"
vendor = "the Fedora Project"
vendor_url = "https://fedoraproject.org/"
def __init__(self, sysroot=None):
super(FedoraPolicy, self).__init__(sysroot=sysroot)
@classmethod
def check(self):
"""This method checks to see if we are running on Fedora. It returns
True or False."""
return os.path.isfile('/etc/fedora-release')
def fedora_version(self):
pkg = self.pkg_by_name("fedora-release") or \
self.all_pkgs_by_name_regex("fedora-release-.*")[-1]
return int(pkg["version"])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/policies/ibmkvm.py 0000644 0001750 0001750 00000004706 12625313241 021765 0 ustar caribou caribou # Copyright (C) IBM Corporation, 2015
#
# Authors: Kamalesh Babulal
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
from __future__ import print_function
from sos.plugins import PowerKVMPlugin, ZKVMPlugin, RedHatPlugin
from sos.policies.redhat import RedHatPolicy
import os
class PowerKVMPolicy(RedHatPolicy):
distro = "PowerKVM"
vendor = "IBM"
vendor_url = "http://www-03.ibm.com/systems/power/software/linux/powerkvm"
def __init__(self):
super(PowerKVMPolicy, self).__init__()
self.valid_subclasses = [PowerKVMPlugin, RedHatPlugin]
@classmethod
def check(self):
"""This method checks to see if we are running on PowerKVM.
It returns True or False."""
return os.path.isfile('/etc/ibm_powerkvm-release')
def dist_version(self):
try:
with open('/etc/ibm_powerkvm-release', 'r') as fp:
version_string = fp.read()
return version_string[2][0]
return False
except:
return False
class ZKVMPolicy(RedHatPolicy):
distro = "IBM Hypervisor"
vendor = "IBM Hypervisor"
vendor_url = "http://www.ibm.com/systems/z/linux/IBMHypervisor/support/"
def __init__(self):
super(ZKVMPolicy, self).__init__()
self.valid_subclasses = [ZKVMPlugin, RedHatPlugin]
@classmethod
def check(self):
"""This method checks to see if we are running on IBM Z KVM. It
returns True or False."""
return os.path.isfile('/etc/base-release')
def dist_version(self):
try:
with open('/etc/base-release', 'r') as fp:
version_string = fp.read()
return version_string.split(' ', 4)[3][0]
return False
except:
return False
# vim: set ts=4 sw=4
sosreport-3.2+git276-g7da50d6/sos/policies/Makefile 0000644 0001750 0001750 00000001104 12433366740 021564 0 ustar caribou caribou PYTHON=python
PACKAGE = $(shell basename `pwd`)
PYFILES = $(wildcard *.py)
PYVER := $(shell $(PYTHON) -c 'import sys; print("%.3s" %(sys.version))')
PYSYSDIR := $(shell $(PYTHON) -c 'import sys; print(sys.prefix)')
PYLIBDIR = $(PYSYSDIR)/lib/python$(PYVER)
PKGDIR = $(PYLIBDIR)/site-packages/sos/$(PACKAGE)
all:
echo "nada"
clean:
rm -f *.pyc *.pyo *~
install:
mkdir -p $(DESTDIR)/$(PKGDIR)
for p in $(PYFILES) ; do \
install -m 644 $$p $(DESTDIR)/$(PKGDIR)/$$p; \
done
$(PYTHON) -c "import compileall; compileall.compile_dir('$(DESTDIR)/$(PKGDIR)', 1, '$(PYDIR)', 1)"
sosreport-3.2+git276-g7da50d6/sos/policies/__init__.py 0000644 0001750 0001750 00000033473 12625313241 022242 0 ustar caribou caribou from __future__ import with_statement
import os
import re
import platform
import time
import fnmatch
import tempfile
from os import environ
from sos.utilities import (ImporterHelper,
import_module,
get_hash_name,
shell_out)
from sos.plugins import IndependentPlugin, ExperimentalPlugin
from sos import _sos as _
import hashlib
from textwrap import fill
from six import print_
from six.moves import input
def import_policy(name):
policy_fqname = "sos.policies.%s" % name
try:
return import_module(policy_fqname, Policy)
except ImportError:
return None
def load(cache={}, sysroot=None):
if 'policy' in cache:
return cache.get('policy')
import sos.policies
helper = ImporterHelper(sos.policies)
for module in helper.get_modules():
for policy in import_policy(module):
if policy.check():
cache['policy'] = policy(sysroot=sysroot)
if 'policy' not in cache:
cache['policy'] = GenericPolicy()
return cache['policy']
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
format:
package name|package.version\n
You may also subclass this class and provide a get_pkg_list method to
build the list of packages and versions.
"""
query_command = None
timeout = 30
chroot = None
def __init__(self, query_command=None, chroot=None):
self.packages = {}
if query_command:
self.query_command = query_command
if chroot:
self.chroot = chroot
def all_pkgs_by_name(self, name):
"""
Return a list of packages that match name.
"""
return fnmatch.filter(self.all_pkgs().keys(), name)
def all_pkgs_by_name_regex(self, regex_name, flags=0):
"""
Return a list of packages that match regex_name.
"""
reg = re.compile(regex_name, flags)
return [pkg for pkg in self.all_pkgs().keys() if reg.match(pkg)]
def pkg_by_name(self, name):
"""
Return a single package that matches name.
"""
pkgmatches = self.all_pkgs_by_name(name)
if (len(pkgmatches) != 0):
return self.all_pkgs_by_name(name)[-1]
else:
return None
def get_pkg_list(self):
"""
returns a dictionary of packages in the following format:
{'package_name': {'name': 'package_name', '
version': 'major.minor.version'}}
"""
if self.query_command:
cmd = self.query_command
pkg_list = shell_out(
cmd, timeout=self.timeout, chroot=self.chroot
).splitlines()
for pkg in pkg_list:
if '|' not in pkg:
continue
name, version = pkg.split("|")
self.packages[name] = {
'name': name,
'version': version.split(".")
}
return self.packages
def all_pkgs(self):
"""
Return a list of all packages.
"""
if not self.packages:
self.packages = self.get_pkg_list()
return self.packages
def pkg_nvra(self, pkg):
fields = pkg.split("-")
version, release, arch = fields[-3:]
name = "-".join(fields[:-3])
return (name, version, release, arch)
class Policy(object):
msg = _("""\
This command will collect system configuration and diagnostic information \
from this %(distro)s system. An archive containing the collected information \
will be generated in %(tmpdir)s.
For more information on %(vendor)s visit:
%(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.
%(vendor_text)s
""")
distro = "Unknown"
vendor = "Unknown"
vendor_url = "http://www.example.com/"
vendor_text = ""
PATH = ""
_in_container = False
_host_sysroot = '/'
def __init__(self, sysroot=None):
"""Subclasses that choose to override this initializer should call
super() to ensure that they get the required platform bits attached.
super(SubClass, self).__init__(). Policies that require runtime
tests to construct PATH must call self.set_exec_path() after
modifying PATH in their own initializer."""
self._parse_uname()
self.report_name = self.hostname
self.case_id = None
self.package_manager = PackageManager()
self._valid_subclasses = []
self.set_exec_path()
self._host_sysroot = sysroot
def get_valid_subclasses(self):
return [IndependentPlugin] + self._valid_subclasses
def set_valid_subclasses(self, subclasses):
self._valid_subclasses = subclasses
def del_valid_subclasses(self):
del self._valid_subclasses
valid_subclasses = property(get_valid_subclasses,
set_valid_subclasses,
del_valid_subclasses,
"list of subclasses that this policy can "
"process")
def check(self):
"""
This function is responsible for determining if the underlying system
is supported by this policy.
"""
return False
def in_container(self):
""" Returns True if sos is running inside a container environment.
"""
return self._in_container
def host_sysroot(self):
return self._host_sysroot
def dist_version(self):
"""
Return the OS version
"""
pass
def get_preferred_archive(self):
"""
Return the class object of the prefered archive format for this
platform
"""
from sos.archive import TarFileArchive
return TarFileArchive
def get_archive_name(self):
"""
This function should return the filename of the archive without the
extension.
"""
if self.case_id:
self.report_name += "." + self.case_id
return "sosreport-%s-%s" % (self.report_name,
time.strftime("%Y%m%d%H%M%S"))
def get_tmp_dir(self, opt_tmp_dir):
if not opt_tmp_dir:
return tempfile.gettempdir()
return opt_tmp_dir
def match_plugin(self, plugin_classes):
if len(plugin_classes) > 1:
for p in plugin_classes:
# Give preference to the first listed tagging class
# so that e.g. UbuntuPlugin is chosen over DebianPlugin
# on an Ubuntu installation.
if issubclass(p, self.valid_subclasses[0]):
return p
return plugin_classes[0]
def validate_plugin(self, plugin_class, experimental=False):
"""
Verifies that the plugin_class should execute under this policy
"""
valid_subclasses = [IndependentPlugin] + self.valid_subclasses
if experimental:
valid_subclasses += [ExperimentalPlugin]
return any(issubclass(plugin_class, class_) for
class_ in valid_subclasses)
def pre_work(self):
"""
This function is called prior to collection.
"""
pass
def post_work(self):
"""
This function is called after the sosreport has been generated.
"""
pass
def pkg_by_name(self, pkg):
return self.package_manager.pkg_by_name(pkg)
def _parse_uname(self):
(system, node, release,
version, machine, processor) = platform.uname()
self.system = system
self.hostname = node
self.release = release
self.smp = version.split()[1] == "SMP"
self.machine = machine
def set_commons(self, commons):
self.commons = commons
def _set_PATH(self, path):
environ['PATH'] = path
def set_exec_path(self):
self._set_PATH(self.PATH)
def is_root(self):
"""This method should return true if the user calling the script is
considered to be a superuser"""
return (os.getuid() == 0)
def _create_checksum(self, final_filename=None):
if not final_filename:
return False
archive_fp = open(final_filename, 'rb')
digest = hashlib.new(get_hash_name())
digest.update(archive_fp.read())
archive_fp.close()
return digest.hexdigest()
def get_preferred_hash_algorithm(self):
"""Returns the string name of the hashlib-supported checksum algorithm
to use"""
return "md5"
def display_results(self, final_filename=None, build=False):
# make sure a report exists
if not final_filename:
return False
self._print()
if not build:
# store checksum into file
fp = open(final_filename + "." + get_hash_name(), "w")
checksum = self._create_checksum(final_filename)
if checksum:
fp.write(checksum + "\n")
fp.close()
self._print(_("Your sosreport has been generated and saved "
"in:\n %s") % final_filename)
else:
checksum = None
self._print(_("sosreport build tree is located at : %s" %
final_filename))
self._print()
if checksum:
self._print(_("The checksum is: ") + checksum)
self._print()
self._print(_("Please send this file to your support "
"representative."))
self._print()
def _print(self, msg=None):
"""A wrapper around print that only prints if we are not running in
quiet mode"""
if not self.commons['cmdlineopts'].quiet:
if msg:
print_(msg)
else:
print_()
def get_msg(self):
"""This method is used to prepare the preamble text to display to
the user in non-batch mode. If your policy sets self.distro that
text will be substituted accordingly. You can also override this
method to do something more complicated."""
width = 72
_msg = self.msg % {'distro': self.distro, 'vendor': self.vendor,
'vendor_url': self.vendor_url,
'vendor_text': self.vendor_text,
'tmpdir': self.commons['tmpdir']}
_fmt = ""
for line in _msg.splitlines():
_fmt = _fmt + fill(line, width, replace_whitespace=False) + '\n'
return _fmt
class GenericPolicy(Policy):
"""This Policy will be returned if no other policy can be loaded. This
should allow for IndependentPlugins to be executed on any system"""
def get_msg(self):
return self.msg % {'distro': self.system}
class LinuxPolicy(Policy):
"""This policy is meant to be an abc class that provides common
implementations used in Linux distros"""
distro = "Linux"
vendor = "None"
PATH = "/bin:/sbin:/usr/bin:/usr/sbin"
def __init__(self, sysroot=None):
super(LinuxPolicy, self).__init__(sysroot=sysroot)
def get_preferred_hash_algorithm(self):
checksum = "md5"
try:
fp = open("/proc/sys/crypto/fips_enabled", "r")
except:
return checksum
fips_enabled = fp.read()
if fips_enabled.find("1") >= 0:
checksum = "sha256"
fp.close()
return checksum
def default_runlevel(self):
try:
with open("/etc/inittab") as fp:
pattern = r"id:(\d{1}):initdefault:"
text = fp.read()
return int(re.findall(pattern, text)[0])
except:
return 3
def kernel_version(self):
return self.release
def host_name(self):
return self.hostname
def is_kernel_smp(self):
return self.smp
def get_arch(self):
return self.machine
def get_local_name(self):
"""Returns the name usd in the pre_work step"""
return self.host_name()
def sanitize_report_name(self, report_name):
return re.sub(r"[^-a-zA-Z.0-9]", "", report_name)
def sanitize_case_id(self, case_id):
return re.sub(r"[^-a-z,A-Z.0-9]", "", case_id)
def pre_work(self):
# this method will be called before the gathering begins
cmdline_opts = self.commons['cmdlineopts']
customer_name = cmdline_opts.customer_name
localname = customer_name if customer_name else self.get_local_name()
caseid = cmdline_opts.case_id if cmdline_opts.case_id else ""
if not cmdline_opts.batch and not \
cmdline_opts.quiet:
try:
self.report_name = input(_("Please enter your first initial "
"and last name [%s]: ") % localname)
self.case_id = input(_("Please enter the case id "
"that you are generating this "
"report for [%s]: ") % caseid)
self._print()
except:
self._print()
self.report_name = localname
if len(self.report_name) == 0:
self.report_name = localname
if customer_name:
self.report_name = customer_name
if cmdline_opts.case_id:
self.case_id = cmdline_opts.case_id
self.report_name = self.sanitize_report_name(self.report_name)
if self.case_id:
self.case_id = self.sanitize_case_id(self.case_id)
if (self.report_name == ""):
self.report_name = "default"
return
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/policies/ubuntu.py 0000644 0001750 0001750 00000002204 12625313241 022011 0 ustar caribou caribou from __future__ import with_statement
from sos.plugins import UbuntuPlugin, DebianPlugin
from sos.policies.debian import DebianPolicy
class UbuntuPolicy(DebianPolicy):
distro = "Ubuntu"
vendor = "Ubuntu"
vendor_url = "http://www.ubuntu.com/"
def __init__(self, sysroot=None):
super(UbuntuPolicy, self).__init__(sysroot=sysroot)
self.valid_subclasses = [UbuntuPlugin, DebianPlugin]
@classmethod
def check(self):
"""This method checks to see if we are running on Ubuntu.
It returns True or False."""
try:
with open('/etc/lsb-release', 'r') as fp:
return "Ubuntu" in fp.read()
except:
return False
def dist_version(self):
""" Returns the version stated in DISTRIB_RELEASE
"""
try:
with open('/etc/lsb-release', 'r') as fp:
lines = fp.readlines()
for line in lines:
if "DISTRIB_RELEASE" in line:
return line.split("=")[1].strip()
return False
except:
return False
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/policies/debian.py 0000644 0001750 0001750 00000002625 12625313241 021720 0 ustar caribou caribou from sos.plugins import DebianPlugin
from sos.policies import PackageManager, LinuxPolicy
import os
class DebianPolicy(LinuxPolicy):
distro = "Debian"
vendor = "the Debian project"
vendor_url = "http://www.debian.org/"
report_name = ""
ticket_number = ""
package_manager = PackageManager(
"dpkg-query -W -f='${Package}|${Version}\\n' \*")
valid_subclasses = [DebianPlugin]
PATH = "/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games" \
+ ":/usr/local/sbin:/usr/local/bin"
def __init__(self, sysroot=None):
super(DebianPolicy, self).__init__(sysroot=sysroot)
self.report_name = ""
self.ticket_number = ""
self.package_manager = PackageManager(
"dpkg-query -W -f='${Package}|${Version}\\n' \*")
self.valid_subclasses = [DebianPlugin]
@classmethod
def check(self):
"""This method checks to see if we are running on Debian.
It returns True or False."""
return os.path.isfile('/etc/debian_version')
def dist_version(self):
try:
with open('/etc/lsb-release', 'r') as fp:
rel_string = fp.read()
if "wheezy/sid" in rel_string:
return 6
elif "jessie/sid" in rel_string:
return 7
return False
except:
return False
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/Makefile 0000644 0001750 0001750 00000001053 12433366740 017760 0 ustar caribou caribou PYTHON=python
PACKAGE = $(shell basename `pwd`)
PYVER := $(shell $(PYTHON) -c 'import sys; print("%.3s" %(sys.version))')
PYSYSDIR := $(shell $(PYTHON) -c 'import sys; print(sys.prefix)')
PYLIBDIR = $(PYSYSDIR)/lib/python$(PYVER)
PKGDIR = $(PYLIBDIR)/site-packages/$(PACKAGE)
all:
echo "nada"
clean:
rm -f *.pyc *.pyo *~
install:
mkdir -p $(DESTDIR)/$(PKGDIR)
for p in $(wildcard *.py) ; do \
install -m 644 $$p $(DESTDIR)/$(PKGDIR)/$$p; \
done
$(PYTHON) -c "import compileall; compileall.compile_dir('$(DESTDIR)/$(PKGDIR)', 1, '$(PYDIR)', 1)"
sosreport-3.2+git276-g7da50d6/sos/__init__.py 0000644 0001750 0001750 00000002140 12605172031 020414 0 ustar caribou caribou # Copyright 2010 Red Hat, Inc.
# Author: Adam Stokes
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
"""
This module houses the i18n setup and message function. The default is to use
gettext to internationalize messages.
"""
import gettext
__version__ = "3.2.0a1"
gettext_dir = "/usr/share/locale"
gettext_app = "sos"
gettext.bindtextdomain(gettext_app, gettext_dir)
def _default(msg):
return gettext.dgettext(gettext_app, msg)
_sos = _default
sosreport-3.2+git276-g7da50d6/sos/__init__.py.in 0000644 0001750 0001750 00000002144 12433366740 021040 0 ustar caribou caribou # Copyright 2010 Red Hat, Inc.
# Author: Adam Stokes
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
"""
This module houses the i18n setup and message function. The default is to use
gettext to internationalize messages.
"""
__version__ = "@SOSVERSION@"
import gettext
gettext_dir = "/usr/share/locale"
gettext_app = "sos"
gettext.bindtextdomain(gettext_app, gettext_dir)
def _default(msg):
return gettext.dgettext(gettext_app, msg)
_sos = _default
sosreport-3.2+git276-g7da50d6/sos/reporting.py 0000644 0001750 0001750 00000007541 12625313241 020702 0 ustar caribou caribou # Copyright (C) 2014 Red Hat, Inc.,
# Bryn M. Reeves
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
""" This provides a restricted tag language to define the sosreport
index/report
"""
try:
import json
except ImportError:
import simplejson as json
# PYCOMPAT
from six import iteritems
class Node(object):
def __str__(self):
return json.dumps(self.data)
def can_add(self, node):
return False
class Leaf(Node):
"""Marker class that can be added to a Section node"""
pass
class Report(Node):
"""The root element of a report. This is a container for sections."""
def __init__(self):
self.data = {}
def can_add(self, node):
return isinstance(node, Section)
def add(self, *nodes):
for node in nodes:
if self.can_add(node):
self.data[node.name] = node.data
class Section(Node):
"""A section is a container for leaf elements. Sections may be nested
inside of Report objects only."""
def __init__(self, name):
self.name = name
self.data = {}
def can_add(self, node):
return isinstance(node, Leaf)
def add(self, *nodes):
for node in nodes:
if self.can_add(node):
self.data.setdefault(node.ADDS_TO, []).append(node.data)
class Command(Leaf):
ADDS_TO = "commands"
def __init__(self, name, return_code, href):
self.data = {"name": name,
"return_code": return_code,
"href": href}
class CopiedFile(Leaf):
ADDS_TO = "copied_files"
def __init__(self, name, href):
self.data = {"name": name,
"href": href}
class CreatedFile(Leaf):
ADDS_TO = "created_files"
def __init__(self, name):
self.data = {"name": name}
class Alert(Leaf):
ADDS_TO = "alerts"
def __init__(self, content):
self.data = content
class Note(Leaf):
ADDS_TO = "notes"
def __init__(self, content):
self.data = content
class PlainTextReport(object):
"""Will generate a plain text report from a top_level Report object"""
LEAF = " * %(name)s"
ALERT = " ! %s"
NOTE = " * %s"
DIVIDER = "=" * 72
subsections = (
(Command, LEAF, "- commands executed:"),
(CopiedFile, LEAF, "- files copied:"),
(CreatedFile, LEAF, "- files created:"),
(Alert, ALERT, "- alerts:"),
(Note, NOTE, "- notes:"),
)
buf = []
def __init__(self, report_node):
self.report_node = report_node
def __str__(self):
self.buf = buf = []
for section_name, section_contents in sorted(iteritems(
self.report_node.data)):
buf.append(section_name + "\n" + self.DIVIDER)
for type_, format_, header in self.subsections:
self.process_subsection(section_contents, type_.ADDS_TO,
header, format_)
return "\n".join(buf)
def process_subsection(self, section, key, header, format_):
if key in section:
self.buf.append(header)
for item in section.get(key):
self.buf.append(format_ % item)
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/ 0000755 0001750 0001750 00000000000 12625313247 017777 5 ustar caribou caribou sosreport-3.2+git276-g7da50d6/sos/plugins/lsbrelease.py 0000644 0001750 0001750 00000002253 12625313241 022466 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class LsbRelease(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
"""Linux standard base
"""
plugin_name = 'lsbrelease'
profiles = ('system',)
def setup(self):
self.add_cmd_output("lsb_release -a")
self.add_cmd_output(
"lsb_release -d", suggest_filename="lsb_release",
root_symlink="lsb-release")
self.add_copy_spec("/etc/lsb-release*")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/fcoe.py 0000644 0001750 0001750 00000002477 12625313241 021271 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin
class fcoe(Plugin, RedHatPlugin):
"""Fibre Channel over Ethernet
"""
plugin_name = 'fcoe'
profiles = ('storage', 'hardware')
packages = ('fcoe-utils',)
def setup(self):
# Here we capture the information about all
# FCoE instances with the -i option, and
# information about all discovered FCFs
# with the -f option
self.add_cmd_output([
"fcoeadm -i",
"fcoeadm -f"
])
# Here we grab information about the
# interfaces's config files
self.add_copy_spec("/etc/fcoe")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/x11.py 0000644 0001750 0001750 00000002456 12625313241 020763 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class X11(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
"""X windowing system
"""
plugin_name = 'x11'
profiles = ('hardware', 'desktop')
files = ('/etc/X11',)
def setup(self):
self.add_copy_spec([
"/etc/X11",
"/var/log/Xorg.*.log",
"/var/log/XFree86.*.log",
])
self.add_forbidden_path("/etc/X11/X")
self.add_forbidden_path("/etc/X11/fontpath.d")
self.add_cmd_output([
"glxinfo",
"xrandr --verbose"
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/monit.py 0000644 0001750 0001750 00000005246 12625313241 021500 0 ustar caribou caribou # Copyright (C) 2015 Red Hat, Inc.,
# Pablo Iranzo Gomez
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin
from glob import glob
class Monit(Plugin, RedHatPlugin):
"""Monit monitoring daemon
"""
packages = ('monit',)
profiles = ('system')
plugin_name = 'monit'
# Define configuration files
monit_conf = glob("/etc/monit.d/*")
monit_conf.append("/etc/monit.conf")
monit_conf.append("/etc/monitrc")
# Define log files
monit_log = ["/var/log/monit.log"]
option_list = []
def setup(self):
self.add_cmd_output("monit status")
self.add_copy_spec([self.monit_log, self.monit_conf])
def postproc(self):
# Post process the files included to scrub any
# password or other sensitive data
# usernames and emails are cleaned to not disclose any
# confidential data
for file in self.monit_conf:
# Remove username:password from files
self.do_file_sub(file,
r"allow (.*):(.*)",
r"allow ********:********"
)
self.do_file_sub(file,
r"ALLOW (.*):(.*)",
r"ALLOW ********:********"
)
# Remove MAILSERVER username/password
self.do_file_sub(file,
r"username (\w)+",
r"username ********"
)
self.do_file_sub(file,
r"password (\w)+",
r"password ********"
)
self.do_file_sub(file,
r"USERNAME (\w)+",
r"USERNAME ********"
)
self.do_file_sub(file,
r"PASSWORD (\w)+",
r"PASSWORD ********"
)
# vim: et ts=4 sw=4
sosreport-3.2+git276-g7da50d6/sos/plugins/sanlock.py 0000644 0001750 0001750 00000002515 12625313241 022000 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin
class SANLock(Plugin):
"""SANlock daemon
"""
plugin_name = "sanlock"
profiles = ('cluster', 'virt')
packages = ["sanlock"]
def setup(self):
self.add_copy_spec("/var/log/sanlock.log*")
self.add_cmd_output([
"sanlock client status -D",
"sanlock client host_status -D",
"sanlock client log_dump"
])
return
class RedHatSANLock(SANLock, RedHatPlugin):
files = ["/etc/sysconfig/sanlock"]
def setup(self):
super(RedHatSANLock, self).setup()
self.add_copy_spec("/etc/sysconfig/sanlock")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/kubernetes.py 0000644 0001750 0001750 00000004256 12625313247 022527 0 ustar caribou caribou # Copyright (C) 2014 Red Hat, Inc. Neependra Khare
# Copyright (C) 2014 Red Hat, Inc. Bryn M. Reeves
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin
class kubernetes(Plugin, RedHatPlugin):
"""Kubernetes plugin
"""
option_list = [("podslog", "capture logs for pods", 'slow', False)]
def setup(self):
self.add_copy_spec("/etc/kubernetes")
self.add_copy_spec("/var/run/flannel")
# Kubernetes master info
self.add_cmd_output("kubectl version")
self.add_cmd_output("kubectl get -o json pods")
self.add_cmd_output("kubectl get -o json nodes")
self.add_cmd_output("kubectl get -o json services")
self.add_cmd_output("kubectl get -o json replicationController")
self.add_cmd_output("kubectl get -o json events")
self.add_cmd_output("journalctl -u kubelet")
self.add_cmd_output("journalctl -u kube-apiserver")
self.add_cmd_output("journalctl -u kube-controller-manager")
self.add_cmd_output("journalctl -u kube-scheduler")
self.add_cmd_output("journalctl -u kube-proxy")
if self.get_option('podslog'):
result = self.get_command_output("kubectl get pods")
if result['status'] == 0:
for line in result['output'].splitlines()[1:]:
pod_name = line.split(" ")[0]
self.add_cmd_output([
"{0} log {1}".format("kubectl", pod_name)
])
# vim: et ts=5 sw=4
sosreport-3.2+git276-g7da50d6/sos/plugins/saphana.py 0000644 0001750 0001750 00000006231 12625313241 021760 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
import os
from sos.plugins import Plugin, RedHatPlugin
class saphana(Plugin, RedHatPlugin):
"""SAP HANA"""
plugin_name = 'saphana'
profiles = ['sap']
files = ['/hana']
def setup(self):
sids = []
if os.path.isdir("/hana/shared"):
s = os.listdir("/hana/shared")
for sid in s:
if len(sid) == 3:
sid = sid.strip()
sids.append(sid)
for sid in sids:
sidadm = '%sadm' % sid.lower()
prefix = 'su - %s -c' % sidadm
self.add_cmd_output('%s "HDB info"' % prefix,
suggest_filename="%s_HDB_info" % sid)
self.add_cmd_output('%s "hdbsrvutil -v"' % prefix,
suggest_filename="%s_version" % sid)
self.add_cmd_output('%s \'hdbcons "mm l -s -S -p"\'' % prefix,
suggest_filename="%s_memusage" % sid)
self.add_cmd_output('%s \'hdbcons -e hdbindexserver \
"replication info"\'' % prefix,
suggest_filename="%s_replicainfo" % sid)
if os.path.isdir("/hana/shared/%s/" % sid):
i = os.listdir("/hana/shared/%s/" % sid)
for inst in i:
if "HDB" in inst:
inst = inst.strip()[-2:]
# get GREEN/RED status
self.add_cmd_output(
'su - %s -c "sapcontrol -nr %s \
-function GetProcessList"'
% (sidadm, inst),
suggest_filename="%s_%s_status"
% (sid, inst)
)
path = '/usr/sap/%s/HDB%s/exe/python_support'
path %= (sid, inst)
if os.path.isdir("%s" % path):
# SCALE OUT - slow
self.add_cmd_output(
'su - %s -c "python \
%s/landscapeHostConfiguration.py"'
% (sidadm, path),
suggest_filename="%s_%s_landscapeConfig"
% (sid, inst)
)
# vim: et ts=4 sw=4
sosreport-3.2+git276-g7da50d6/sos/plugins/openstack_heat.py 0000644 0001750 0001750 00000004623 12625313247 023346 0 ustar caribou caribou # Copyright (C) 2013 Red Hat, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class OpenStackHeat(Plugin):
"""OpenStack Heat
"""
plugin_name = "openstack_heat"
profiles = ('openstack', 'openstack_controller')
option_list = []
def setup(self):
# Heat
self.add_cmd_output(
"heat-manage db_version",
suggest_filename="heat_db_version"
)
self.limit = self.get_option("log_size")
if self.get_option("all_logs"):
self.add_copy_spec_limit("/var/log/heat/",
sizelimit=self.limit)
else:
self.add_copy_spec_limit("/var/log/heat/*.log",
sizelimit=self.limit)
self.add_copy_spec("/etc/heat/")
def postproc(self):
protect_keys = [
"admin_password", "memcache_secret_key", "password", "connection",
"qpid_password", "rabbit_password", "stack_domain_admin_password",
]
regexp = r"((?m)^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys)
self.do_path_regex_sub("/etc/heat/*", regexp, r"\1*********")
class DebianHeat(OpenStackHeat, DebianPlugin, UbuntuPlugin):
packages = (
'heat-api',
'heat-api-cfn',
'heat-api-cloudwatch',
'heat-common',
'heat-engine',
'python-heat',
'python-heatclient'
)
class RedHatHeat(OpenStackHeat, RedHatPlugin):
packages = (
'openstack-heat-api',
'openstack-heat-api-cfn',
'openstack-heat-api-cloudwatch',
'openstack-heat-cli',
'openstack-heat-common',
'openstack-heat-engine',
'python-heatclient'
)
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/mpt.py 0000644 0001750 0001750 00000002120 12625313241 021136 0 ustar caribou caribou # Copyright (C) 2015 Red Hat, Inc., Bryn M. Reeves
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Mpt(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
""" LSI Message Passing Technology
"""
files = ('/proc/mpt',)
profiles = ('storage', )
plugin_name = 'mpt'
def setup(self):
self.add_copy_spec("/proc/mpt")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/ata.py 0000644 0001750 0001750 00000002741 12625313241 021114 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, UbuntuPlugin, DebianPlugin
import os
class Ata(Plugin, RedHatPlugin, UbuntuPlugin, DebianPlugin):
""" ATA and IDE information
"""
plugin_name = "ata"
profiles = ('storage', 'hardware')
packages = ('hdparm', 'smartmontools')
def setup(self):
dev_path = '/dev'
sys_block = '/sys/block'
self.add_copy_spec('/proc/ide')
if os.path.isdir(sys_block):
for disk in os.listdir(sys_block):
if disk.startswith("sd") or disk.startswith("hd"):
disk_path = os.path.join(dev_path, disk)
self.add_cmd_output([
"hdparm %s" % disk_path,
"smartctl -a %s" % disk_path
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/apt.py 0000644 0001750 0001750 00000003235 12625313241 021132 0 ustar caribou caribou # Copyright (C) 2013 Louis Bouchard
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, UbuntuPlugin, DebianPlugin
class Apt(Plugin, DebianPlugin, UbuntuPlugin):
""" APT - advanced packaging tool
"""
plugin_name = 'apt'
profiles = ('system', 'sysmgmt', 'packagemanager')
def setup(self):
self.add_copy_spec([
"/etc/apt", "/var/log/apt"
])
self.add_cmd_output([
"apt-get check",
"apt-config dump",
"apt-cache stats",
"apt-cache policy"
])
dpkg_result = self.call_ext_prog(
"dpkg-query -W -f='${binary:Package}\t${status}\n'")
dpkg_output = dpkg_result['output'].splitlines()
pkg_list = ' '.join(
[v.split('\t')[0] for v in dpkg_output if 'ok installed' in v])
self.add_cmd_output(
"apt-cache policy {}".format(pkg_list),
suggest_filename="apt-cache_policy_details"
)
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/nfsserver.py 0000644 0001750 0001750 00000003463 12625313241 022366 0 ustar caribou caribou # Copyright (C) 2007 Red Hat, Inc., Eugene Teo
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin
import os
from stat import ST_SIZE
class NfsServer(Plugin, RedHatPlugin):
"""NFS server information
"""
plugin_name = 'nfsserver'
profiles = ('storage', 'network', 'services', 'nfs')
def check_enabled(self):
default_runlevel = self.policy().default_runlevel()
nfs_runlevels = self.policy().runlevel_by_service("nfs")
if default_runlevel in nfs_runlevels:
return True
try:
exports = os.stat("/etc/exports")[ST_SIZE]
xtab = os.stat("/var/lib/nfs/xtab")[ST_SIZE]
if exports or xtab:
return True
except:
pass
return False
def setup(self):
self.add_copy_spec([
"/etc/exports",
"/etc/exports.d",
"/var/lib/nfs/etab",
"/var/lib/nfs/xtab",
"/var/lib/nfs/rmtab"
])
self.add_cmd_output([
"rpcinfo -p localhost",
"nfsstat -o all",
"exportfs -v"
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/ipvs.py 0000644 0001750 0001750 00000002156 12625313241 021330 0 ustar caribou caribou # Copyright (C) 2014 Red Hat, Inc. Bryn M. Reeves
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin
class Ipvs(Plugin, RedHatPlugin, DebianPlugin):
"""Linux IP virtual server
"""
plugin_name = 'ipvs'
profiles = ('cluster', 'network')
packages = ('ipvsadm',)
def setup(self):
self.add_cmd_output([
"ipvsadm -Ln",
"ipvsadm -Lc"
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/openstack_sahara.py 0000644 0001750 0001750 00000005336 12625313247 023666 0 ustar caribou caribou # Copyright (C) 2015 Red Hat, Inc.,Poornima M. Kshirsagar
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class OpenStackSahara(Plugin):
"""OpenStack Sahara"""
plugin_name = 'openstack_sahara'
profiles = ('openstack', 'openstack_controller')
option_list = []
def setup(self):
self.add_copy_spec("/etc/sahara/")
self.add_cmd_output("journalctl -u openstack-sahara-all")
self.add_cmd_output("journalctl -u openstack-sahara-api")
self.add_cmd_output("journalctl -u openstack-sahara-engine")
self.limit = self.get_option("log_size")
if self.get_option("all_logs"):
self.add_copy_spec_limit("/var/log/sahara/",
sizelimit=self.limit)
else:
self.add_copy_spec_limit("/var/log/sahara/*.log",
sizelimit=self.limit)
def postproc(self):
protect_keys = [
"admin_password", "memcache_secret_key", "password",
"qpid_password", "rabbit_password", "ssl_key_password",
"xenapi_connection_password", "connection"
]
regexp = r"((?m)^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys)
self.do_path_regex_sub("/etc/sahara/*", regexp, r"\1*********")
class DebianSahara(OpenStackSahara, DebianPlugin, UbuntuPlugin):
"""OpenStackSahara related information for Debian based distributions."""
packages = (
'sahara-api',
'sahara-common',
'sahara-engine',
'python-sahara',
'python-saharaclient',
)
def setup(self):
super(DebianSahara, self).setup()
class RedHatSahara(OpenStackSahara, RedHatPlugin):
"""OpenStack sahara related information for Red Hat distributions."""
packages = (
'openstack-sahara',
'openstack-sahara-api',
'openstack-sahara-engine',
'python-saharaclient'
)
def setup(self):
super(RedHatSahara, self).setup()
self.add_copy_spec("/etc/sudoers.d/sahara")
# vim: et ts=4 sw=4
sosreport-3.2+git276-g7da50d6/sos/plugins/sapnw.py 0000644 0001750 0001750 00000013413 12625313241 021475 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
import os
from sos.plugins import Plugin, RedHatPlugin
def get_directory_listing(path):
try:
dir_list = os.listdir(path)
except:
dir_list = []
return dir_list
class sapnw(Plugin, RedHatPlugin):
"""SAP NetWeaver"""
plugin_name = 'sapnw'
profiles = ['sap']
files = ['/usr/sap']
def collect_list_instances(self):
# list installed instances
inst_out = self.get_cmd_output_now("/usr/sap/hostctrl/exe/saphostctrl \
-function ListInstances",
suggest_filename="SAPInstances")
if not inst_out:
return
sidsunique = set()
# Cycle through all the instances, get 'sid', 'instance_number'
# and 'vhost' to determine the proper profile
p = open(inst_out, "r").read().splitlines()
for line in p:
if "DAA" not in line:
fields = line.strip().split()
sid = fields[3]
inst = fields[5]
vhost = fields[7]
sidsunique.add(sid)
for line in get_directory_listing("/usr/sap/%s/SYS/profile/"
% sid):
if sid in line and inst in line and vhost in line:
ldenv = 'LD_LIBRARY_PATH=/usr/sap/%s/SYS/exe/run' % sid
# TODO: I am assuming unicode here
# nuc should be accounted
pt = '/usr/sap/%s/SYS/exe/uc/linuxx86_64' % sid
profile = line.strip()
# collect profiles
self.add_cmd_output(
"env -i %s %s/sappfpar \
all pf=/usr/sap/%s/SYS/profile/%s"
% (ldenv, pt, sid, profile),
suggest_filename="%s_parameters" % profile)
# collect instance status
self.add_cmd_output(
"env -i %s %s/sapcontrol -nr %s \
-function GetProcessList" % (ldenv, pt, inst),
suggest_filename="%s_%s_GetProcList"
% (sid, inst))
# collect version info for the various components
self.add_cmd_output(
"env -i %s %s/sapcontrol -nr %s \
-function GetVersionInfo" % (ldenv, pt, inst),
suggest_filename="%s_%s_GetVersInfo"
% (sid, inst))
# collect adm user environment
lowsid = sid.lower()
self.add_cmd_output(
"su - %sadm -c \"sapcontrol -nr %s -function \
GetEnvironment\"" % (lowsid, inst),
suggest_filename="%s_%sadm_%s_userenv"
% (sid, lowsid, inst))
# traverse the sids list, collecting info about dbclient
for sid in sidsunique:
for line in get_directory_listing("/usr/sap/%s/" % sid):
if 'DVEB' in line:
self.add_cmd_output(
"grep 'client driver' /usr/sap/%s/%s/work/dev_w0"
% (sid, line), suggest_filename="%s_dbclient"
% sid)
def collect_list_dbs(self):
# list installed sap dbs
db_out = self.get_cmd_output_now("/usr/sap/hostctrl/exe/saphostctrl \
-function ListDatabases",
suggest_filename="SAPDatabases")
if not db_out:
return
dbl = open(db_out, "r").read().splitlines()
for line in dbl:
if "Instance name" in line:
fields = line.strip().split()
dbadm = fields[2][:-1]
dbtype = fields[8][:-1]
sid = dbadm[3:].upper()
if dbtype == 'db6':
# IBM DB2
self.add_cmd_output(
"su - %s -c \"db2 get dbm cfg\""
% dbadm, suggest_filename="%s_%s_db2_info"
% (sid, dbadm))
if dbtype == 'sap':
# SAP MAXDB
sid = fields[2][:-1]
self.add_copy_spec(
"/sapdb/%s/data/config/%s.pah" % (sid, sid))
if dbtype == 'ora':
# Oracle
sid = fields[2][:-1]
self.add_copy_spec("/oracle/%s/*/dbs/init.ora" % sid)
if dbtype == 'syb':
# Sybase
sid = fields[2][:-1]
self.add_copy_spec("/sybase/%s/ASE*/%s.cfg" % (sid, sid))
def setup(self):
self.collect_list_instances()
self.collect_list_dbs()
# run sapconf in check mode
self.add_cmd_output("sapconf -n",
suggest_filename="sapconf_checkmode")
# vim: et ts=4 sw=4
sosreport-3.2+git276-g7da50d6/sos/plugins/rpm.py 0000644 0001750 0001750 00000005165 12625313241 021150 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin
class Rpm(Plugin, RedHatPlugin):
"""RPM Package Manager
"""
plugin_name = 'rpm'
profiles = ('system', 'packagemanager')
option_list = [("rpmq", "queries for package information via rpm -q",
"fast", True),
("rpmva", "runs a verify on all packages", "slow", False)]
verify_list = [
'kernel$', 'glibc', 'initscripts',
'pam_.*',
'java.*', 'perl.*',
'rpm', 'yum',
'spacewalk.*',
]
def setup(self):
self.add_copy_spec("/var/log/rpmpkgs")
if self.get_option("rpmq"):
query_fmt = '"%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}~~'
query_fmt = query_fmt + '%{INSTALLTIME:date}\t%{INSTALLTIME}\t'
query_fmt = query_fmt + '%{VENDOR}\t%{BUILDHOST}\t'
query_fmt = query_fmt + '%{SIGPGP}\t%{SIGPGP:pgpsig}\n"'
rpmq_cmd = "rpm --nodigest -qa --qf=%s" % query_fmt
filter_cmd = 'awk -F "~~" ' \
'"{printf \\"%-59s %s\\n\\",\$1,\$2}"|sort'
shell_cmd = "sh -c '%s'" % (rpmq_cmd + "|" + filter_cmd)
self.add_cmd_output(shell_cmd, root_symlink="installed-rpms")
if self.get_option("verify"):
if self.get_option("rpmva"):
self.add_cmd_output("rpm -Va", root_symlink="rpm-Va",
timeout=180)
else:
pkgs_by_regex = \
self.policy().package_manager.all_pkgs_by_name_regex
verify_list = map(pkgs_by_regex, self.verify_list)
verify_pkgs = ""
for pkg_list in verify_list:
for pkg in pkg_list:
if 'debuginfo' in pkg or 'devel' in pkg:
continue
verify_pkgs = "%s %s" % (verify_pkgs, pkg)
self.add_cmd_output("rpm -V %s" % verify_pkgs)
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/snmp.py 0000644 0001750 0001750 00000002507 12625313241 021324 0 ustar caribou caribou # Copyright (C) 2007 Sadique Puthen
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Snmp(Plugin):
"""Simple network management protocol
"""
plugin_name = "snmp"
profiles = ('system', 'sysmgmt')
files = ('/etc/snmp/snmpd.conf',)
def setup(self):
self.add_copy_spec("/etc/snmp")
class RedHatSnmp(Snmp, RedHatPlugin):
packages = ('net-snmp',)
def setup(self):
super(RedHatSnmp, self).setup()
class DebianSnmp(Snmp, DebianPlugin, UbuntuPlugin):
packages = ('snmp',)
def setup(self):
super(DebianSnmp, self).setup()
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/openstack_ceilometer.py 0000644 0001750 0001750 00000005524 12625313247 024556 0 ustar caribou caribou # Copyright (C) 2013 Red Hat, Inc., Eoghan Lynn
# Copyright (C) 2012 Rackspace US, Inc.
# 2012 Justin Shepherd
# Copyright (C) 2009 Red Hat, Inc.
# 2009 Joey Boggs
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class OpenStackCeilometer(Plugin):
"""Openstack Ceilometer"""
plugin_name = "openstack_ceilometer"
profiles = ('openstack', 'openstack_controller', 'openstack_compute')
option_list = []
def setup(self):
# Ceilometer
self.limit = self.get_option("log_size")
if self.get_option("all_logs"):
self.add_copy_spec_limit("/var/log/ceilometer/",
sizelimit=self.limit)
else:
self.add_copy_spec_limit("/var/log/ceilometer/*.log",
sizelimit=self.limit)
self.add_copy_spec("/etc/ceilometer/")
def postproc(self):
protect_keys = [
"admin_password", "connection_password", "host_password",
"memcache_secret_key", "os_password", "password", "qpid_password",
"rabbit_password", "readonly_user_password", "secret_key",
"ssl_key_password", "telemetry_secret", "connection",
"metering_secret"
]
regexp = r"((?m)^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys)
self.do_path_regex_sub("/etc/ceilometer/*", regexp, r"\1*********")
class DebianCeilometer(OpenStackCeilometer, DebianPlugin,
UbuntuPlugin):
packages = (
'ceilometer-api',
'ceilometer-agent-central',
'ceilometer-agent-compute',
'ceilometer-collector',
'ceilometer-common',
'python-ceilometer',
'python-ceilometerclient'
)
class RedHatCeilometer(OpenStackCeilometer, RedHatPlugin):
packages = (
'openstack-ceilometer',
'openstack-ceilometer-api',
'openstack-ceilometer-central',
'openstack-ceilometer-collector',
'openstack-ceilometer-common',
'openstack-ceilometer-compute',
'python-ceilometerclient'
)
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/azure.py 0000644 0001750 0001750 00000002400 12625313241 021465 0 ustar caribou caribou # Copyright (C) 2013 Adam Stokes
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, UbuntuPlugin
class Azure(Plugin, UbuntuPlugin):
""" Microsoft Azure client
"""
plugin_name = 'azure'
profiles = ('virt',)
packages = ('walinuxagent',)
def setup(self):
self.add_copy_spec([
"/var/log/waagent*",
"/var/lib/cloud",
"/etc/default/kv-kvp-daemon-init",
"/sys/module/hv_netvsc/parameters/ring_size",
"/sys/module/hv_storvsc/parameters/storvsc_ringbuffer_size"
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/cs.py 0000644 0001750 0001750 00000007074 12625313241 020760 0 ustar caribou caribou # Copyright (C) 2007-2010 Red Hat, Inc., Kent Lamb
# Marc Sauton
# Pierre Carrier
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin
from os.path import exists
from glob import glob
class CertificateSystem(Plugin, RedHatPlugin):
"""Certificate System and Dogtag
"""
plugin_name = 'certificatesystem'
profiles = ('identity', 'security')
packages = (
"redhat-cs",
"rhpki-common",
"pki-common"
)
files = (
"/opt/redhat-cs",
"/usr/share/java/rhpki",
"/usr/share/java/pki"
)
def checkversion(self):
if self.is_installed("redhat-cs") or exists("/opt/redhat-cs"):
return 71
elif self.is_installed("rhpki-common") or \
len(glob("/var/lib/rhpki-*")):
return 73
# 8 should cover dogtag
elif self.is_installed("pki-common") or exists("/usr/share/java/pki"):
return 8
return False
def setup(self):
csversion = self.checkversion()
if not csversion:
self.add_alert("Red Hat Certificate System not found.")
return
if csversion == 71:
self.add_copy_spec([
"/opt/redhat-cs/slapd-*/logs/access",
"/opt/redhat-cs/slapd-*/logs/errors",
"/opt/redhat-cs/slapd-*/config/dse.ldif",
"/opt/redhat-cs/cert-*/errors",
"/opt/redhat-cs/cert-*/config/CS.cfg",
"/opt/redhat-cs/cert-*/access",
"/opt/redhat-cs/cert-*/errors",
"/opt/redhat-cs/cert-*/system",
"/opt/redhat-cs/cert-*/transactions",
"/opt/redhat-cs/cert-*/debug",
"/opt/redhat-cs/cert-*/tps-debug.log"
])
if csversion == 73:
self.add_copy_spec([
"/var/lib/rhpki-*/conf/*cfg*",
"/var/lib/rhpki-*/conf/*.ldif",
"/var/lib/rhpki-*/logs/debug",
"/var/lib/rhpki-*/logs/catalina.*",
"/var/lib/rhpki-*/logs/ra-debug.log",
"/var/lib/rhpki-*/logs/transactions",
"/var/lib/rhpki-*/logs/system"
])
if csversion in (73, 8):
self.add_copy_spec([
"/etc/dirsrv/slapd-*/dse.ldif",
"/var/log/dirsrv/slapd-*/access",
"/var/log/dirsrv/slapd-*/errors"
])
if csversion == 8:
self.add_copy_spec([
"/etc/pki-*/CS.cfg",
"/var/lib/pki-*/conf/*cfg*",
"/var/log/pki-*/debug",
"/var/log/pki-*/catalina.*",
"/var/log/pki-*/ra-debug.log",
"/var/log/pki-*/transactions",
"/var/log/pki-*/system"
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/pcp.py 0000644 0001750 0001750 00000013667 12625313241 021142 0 ustar caribou caribou # Copyright (C) 2014 Michele Baldessari
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin
import os
import os.path
from socket import gethostname
class Pcp(Plugin, RedHatPlugin, DebianPlugin):
"""Performance Co-Pilot data
"""
plugin_name = 'pcp'
profiles = ('system', 'performance')
packages = ('pcp',)
pcp_conffile = '/etc/pcp.conf'
# size-limit total PCP log data collected by default (MB)
pcplog_totalsize = 100
pcp_sysconf_dir = None
pcp_var_dir = None
pcp_log_dir = None
pcp_hostname = ''
def get_size(self, path):
total_size = 0
for dirpath, dirnames, filenames in os.walk(path):
for f in filenames:
fp = os.path.join(dirpath, f)
total_size += os.path.getsize(fp)
return total_size
def pcp_parse_conffile(self):
try:
pcpconf = open(self.pcp_conffile, "r")
lines = pcpconf.readlines()
pcpconf.close()
except:
return False
env_vars = {}
for line in lines:
if line.startswith('#'):
continue
try:
(key, value) = line.strip().split('=')
env_vars[key] = value
except:
pass
try:
self.pcp_sysconf_dir = env_vars['PCP_SYSCONF_DIR']
self.pcp_var_dir = env_vars['PCP_VAR_DIR']
self.pcp_log_dir = env_vars['PCP_LOG_DIR']
except:
# Fail if all three env variables are not found
return False
return True
def setup(self):
if self.get_option("all_logs"):
self.pcplog_totalsize = 0
if not self.pcp_parse_conffile():
self._log_warn("could not parse %s" % self.pcp_conffile)
return
# Add PCP_SYSCONF_DIR (/etc/pcp) and PCP_VAR_DIR (/var/lib/pcp/config)
# unconditionally. Obviously if someone messes up their /etc/pcp.conf
# in a ridiculous way (i.e. setting PCP_SYSCONF_DIR to '/') this will
# break badly.
var_conf_dir = os.path.join(self.pcp_var_dir, 'config')
self.add_copy_spec([
self.pcp_sysconf_dir,
self.pcp_conffile,
var_conf_dir
])
# We explicitely avoid /var/lib/pcp/config/{pmchart,pmlogconf,pmieconf,
# pmlogrewrite} as in 99% of the cases they are just copies from the
# rpms. It does not make up for a lot of size but it contains many
# files
self.add_forbidden_path(os.path.join(var_conf_dir, 'pmchart'))
self.add_forbidden_path(os.path.join(var_conf_dir, 'pmlogconf'))
self.add_forbidden_path(os.path.join(var_conf_dir, 'pmieconf'))
self.add_forbidden_path(os.path.join(var_conf_dir, 'pmlogrewrite'))
# The *default* directory structure for pmlogger is the following:
# Dir: PCP_LOG_DIR/pmlogger/HOST/ (we only collect the HOST data
# itself)
# - YYYYMMDD.HH.MM.{N,N.index,N.meta} N in [0,1,...]
# - Latest
# - pmlogger.{log,log.prior}
#
# Can be changed via configuration in PCP_SYSCONF_DIR/pmlogger/control
# As a default strategy, collect PCP_LOG_DIR/pmlogger/* only if the
# total size is moderately small: < 100MB. Override is possible via
# the 'all_pcplogs' option.
# FIXME: Doing a recursive size check because add_copy_spec_limit
# won't work for directory trees. I.e. we can't say fetch /foo/bar/
# only if it is < 100MB. To be killed once the Plugin base class will
# add a method for this use case via issue #281
self.pcp_hostname = gethostname()
# Make sure we only add PCP_LOG_DIR/pmlogger/`hostname` if hostname
# is set, otherwise we'd collect everything
if self.pcp_hostname != '':
path = os.path.join(self.pcp_log_dir, 'pmlogger',
self.pcp_hostname)
dirsize = self.get_size(path)
max_mb_size = self.pcplog_totalsize * 1024 * 1024
# If explicitely asked collect all logs, otherwise only if < 100MB
# in total
if self.pcplog_totalsize == 0 or dirsize < max_mb_size:
if os.path.isdir(path):
self.add_copy_spec(path)
else:
self._log_warn("%s not found" % path)
else:
self._log_warn("skipped %s. Size %d bigger than %d"
% (path, dirsize, max_mb_size))
else:
self._log_warn("pcp_hostname was not set. Skipping.")
self.add_copy_spec([
# Collect PCP_LOG_DIR/pmcd and PCP_LOG_DIR/NOTICES
os.path.join(self.pcp_log_dir, 'pmcd'),
os.path.join(self.pcp_log_dir, 'NOTICES*'),
# Collect PCP_VAR_DIR/pmns
os.path.join(self.pcp_var_dir, 'pmns'),
# Also collect any other log and config files
# (as suggested by fche)
os.path.join(self.pcp_log_dir, '*/*.log*'),
os.path.join(self.pcp_log_dir, '*/*/*.log*'),
os.path.join(self.pcp_log_dir, '*/*/config*')
])
# Need to get the current status of the PCP infrastructure
self.add_cmd_output("pcp")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/etcd.py 0000644 0001750 0001750 00000002616 12625313241 021267 0 ustar caribou caribou # Copyright (C) 2015 Red Hat, Inc. Neependra Khare
# Copyright (C) 2015 Red Hat, Inc. Bryn M. Reeves
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin
class etcd(Plugin, RedHatPlugin):
"""etcd plugin
"""
def setup(self):
self.add_copy_spec("/etc/etcd")
self.add_cmd_output("curl http://localhost:4001/version")
self.add_cmd_output("curl http://localhost:4001/v2/members")
self.add_cmd_output("curl http://localhost:4001/v2/stats/leader")
self.add_cmd_output("curl http://localhost:4001/v2/stats/self")
self.add_cmd_output("curl http://localhost:4001/v2/stats/store")
self.add_cmd_output("ls -lR /var/lib/etcd/")
# vim: et ts=5 sw=4
sosreport-3.2+git276-g7da50d6/sos/plugins/yum.py 0000644 0001750 0001750 00000004563 12625313241 021165 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin
class Yum(Plugin, RedHatPlugin):
"""yum information
"""
plugin_name = 'yum'
profiles = ('system', 'packagemanager', 'sysmgmt')
files = ('/etc/yum.conf',)
packages = ('yum',)
option_list = [
("yumlist", "list repositories and packages", "slow", False),
("yumdebug", "gather yum debugging data", "slow", False)
]
def setup(self):
# Pull all yum related information
self.add_copy_spec([
"/etc/yum",
"/etc/yum.repos.d",
"/etc/yum.conf",
"/var/log/yum.log"
])
# Get a list of channels the machine is subscribed to.
self.add_cmd_output("yum -C repolist")
# candlepin info
self.add_forbidden_path("/etc/pki/entitlement/key.pem")
self.add_forbidden_path("/etc/pki/entitlement/*-key.pem")
self.add_copy_spec([
"/etc/pki/product/*.pem",
"/etc/pki/consumer/cert.pem",
"/etc/pki/entitlement/*.pem"
])
self.add_cmd_output("yum history")
if self.get_option("yumlist"):
# List various information about available packages
self.add_cmd_output("yum list")
if self.get_option("yumdebug") and self.is_installed('yum-utils'):
# RHEL6+ alternative for this whole function:
# self.add_cmd_output("yum-debug-dump '%s'"
# % os.path.join(self.commons['dstroot'],"yum-debug-dump"))
r = self.call_ext_prog("yum-debug-dump")
try:
self.add_cmd_output("zcat %s" % (r['output'].split()[-1],))
except IndexError:
pass
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/radius.py 0000644 0001750 0001750 00000003307 12625313241 021635 0 ustar caribou caribou # Copyright (C) 2007 Navid Sheikhol-Eslami
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Radius(Plugin):
"""RADIUS service information
"""
plugin_name = "radius"
profiles = ('network', 'identity')
packages = ('freeradius',)
class RedHatRadius(Radius, RedHatPlugin):
files = ('/etc/raddb',)
def setup(self):
super(RedHatRadius, self).setup()
self.add_copy_spec([
"/etc/raddb",
"/etc/pam.d/radiusd",
"/var/log/radius"
])
def postproc(self):
self.do_file_sub(
"/etc/raddb/sql.conf", r"(\s*password\s*=\s*)\S+", r"\1***")
class DebianRadius(Radius, DebianPlugin, UbuntuPlugin):
files = ('/etc/freeradius',)
def setup(self):
super(DebianRadius, self).setup()
self.add_copy_spec([
"/etc/freeradius",
"/etc/pam.d/radiusd",
"/etc/default/freeradius",
"/var/log/freeradius"
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/auditd.py 0000644 0001750 0001750 00000002701 12625313241 021615 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Auditd(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
"""Audit daemon information
"""
plugin_name = 'auditd'
profiles = ('system', 'security')
packages = ('audit',)
def setup(self):
self.add_copy_spec([
"/etc/audit/auditd.conf",
"/etc/audit/audit.rules"
])
self.add_cmd_output("ausearch --input-logs -m avc,user_avc -ts today")
if not self.get_option("all_logs"):
limit = self.get_option("log_size")
self.add_copy_spec_limit("/var/log/audit/audit.log",
sizelimit=limit)
else:
self.add_copy_spec("/var/log/audit")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/dmraid.py 0000644 0001750 0001750 00000003161 12625313241 021604 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Dmraid(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
"""dmraid software RAID
"""
plugin_name = 'dmraid'
profiles = ('hardware', 'storage')
option_list = [
("metadata", "capture dmraid device metadata", "slow", False)
]
# V - {-V/--version}
# b - {-b|--block_devices}
# r - {-r|--raid_devices}
# s - {-s|--sets}
# t - [-t|--test]
# a - {-a|--activate} {y|n|yes|no}
# D - [-D|--dump_metadata]
dmraid_options = ['V', 'b', 'r', 's', 'tay']
def setup(self):
for opt in self.dmraid_options:
self.add_cmd_output("dmraid -%s" % (opt,))
if self.get_option("metadata"):
metadata_path = self.get_cmd_output_path("metadata")
self.add_cmd_output("dmraid -rD", runat=metadata_path,
chroot=self.tmp_in_sysroot())
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/hts.py 0000644 0001750 0001750 00000002017 12625313241 021141 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin
class HardwareTestSuite(Plugin, RedHatPlugin):
"""Red Hat Hardware Test Suite
"""
plugin_name = 'hardwaretestsuite'
profiles = ('debug',)
def setup(self):
self.add_copy_spec([
"/etc/httpd/conf.d/hts.conf",
"/var/hts"
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/cron.py 0000644 0001750 0001750 00000002441 12625313241 021305 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Cron(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
"""Cron job scheduler
"""
plugin_name = "cron"
profiles = ('system',)
files = ('/etc/crontab')
def setup(self):
self.add_copy_spec([
"/etc/cron*",
"/var/log/cron",
"/var/spool/cron"
])
if self.get_option("all_logs"):
self.add_copy_spec("/var/log/cron*")
self.add_cmd_output("crontab -l -u root",
suggest_filename="root_crontab")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/ovirt.py 0000644 0001750 0001750 00000015657 12625313241 021524 0 ustar caribou caribou # Copyright (C) 2014 Red Hat, Inc., Sandro Bonazzola
# Copyright (C) 2014 Red Hat, Inc., Bryn M. Reeves
# Copyright (C) 2010 Red Hat, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
import os
import re
import signal
from sos.plugins import Plugin, RedHatPlugin
# Class name must be the same as file name and method names must not change
class Ovirt(Plugin, RedHatPlugin):
"""oVirt Engine"""
plugin_name = "ovirt"
profiles = ('virt',)
packages = (
'ovirt-engine',
'ovirt-engine-dwh',
'ovirt-engine-reports',
'ovirt-scheduler-proxy',
'rhevm',
'rhevm-dwh',
'rhevm-reports'
)
DB_PASS_FILES = re.compile(
flags=re.VERBOSE,
pattern=r"""
^
/etc/
(rhevm|ovirt-engine|ovirt-engine-dwh)/
(engine.conf|ovirt-engine-dwhd.conf)
(\.d/.+.conf)?
$
"""
)
DEFAULT_SENSITIVE_KEYS = (
'ENGINE_DB_PASSWORD:ENGINE_PKI_TRUST_STORE_PASSWORD:'
'ENGINE_PKI_ENGINE_STORE_PASSWORD:DWH_DB_PASSWORD'
)
option_list = [
('jbosstrace', 'Enable oVirt Engine JBoss stack trace collection',
'', True),
('sensitive_keys', 'Sensitive keys to be masked',
'', DEFAULT_SENSITIVE_KEYS)
]
def setup(self):
if self.get_option('jbosstrace'):
engine_pattern = "^ovirt-engine\ -server.*jboss-modules.jar"
pgrep = "pgrep -f '%s'" % engine_pattern
lines = self.call_ext_prog(pgrep)['output'].splitlines()
engine_pids = [int(x) for x in lines]
if not engine_pids:
self.soslog.error('Unable to get ovirt-engine pid')
self.add_alert('Unable to get ovirt-engine pid')
for pid in engine_pids:
try:
# backtrace written to '/var/log/ovirt-engine/console.log
os.kill(pid, signal.SIGQUIT)
except OSError as e:
self.soslog.error('Unable to send signal to %d' % pid, e)
self.add_forbidden_path('/etc/ovirt-engine/.pgpass')
self.add_forbidden_path('/etc/rhevm/.pgpass')
# Copy all engine tunables and domain information
self.add_cmd_output("engine-config --all")
self.add_cmd_output("engine-manage-domains list")
# Copy engine config files.
self.add_copy_spec([
"/etc/ovirt-engine",
"/etc/rhevm/",
"/etc/ovirt-engine-dwh",
"/etc/ovirt-engine-reports",
"/var/log/ovirt-engine",
"/var/log/ovirt-engine-dwh",
"/var/log/ovirt-engine-reports",
"/var/log/ovirt-scheduler-proxy",
"/var/log/rhevm",
"/etc/sysconfig/ovirt-engine",
"/usr/share/ovirt-engine/conf",
"/var/log/ovirt-guest-agent",
"/var/lib/ovirt-engine/setup-history.txt",
"/var/lib/ovirt-engine/setup/answers",
"/var/lib/ovirt-engine/external_truststore",
"/var/tmp/ovirt-engine/config",
"/var/lib/ovirt-engine/jboss_runtime/config",
"/var/lib/ovirt-engine-reports/jboss_runtime/config"
])
def postproc(self):
"""
Obfuscate sensitive keys.
"""
self.do_file_sub(
"/etc/ovirt-engine/engine-config/engine-config.properties",
r"Password.type=(.*)",
r"Password.type=********"
)
self.do_file_sub(
"/etc/rhevm/rhevm-config/rhevm-config.properties",
r"Password.type=(.*)",
r"Password.type=********"
)
engine_files = (
'ovirt-engine.xml',
'ovirt-engine_history/current/ovirt-engine.v1.xml',
'ovirt-engine_history/ovirt-engine.boot.xml',
'ovirt-engine_history/ovirt-engine.initial.xml',
'ovirt-engine_history/ovirt-engine.last.xml',
)
for filename in engine_files:
self.do_file_sub(
"/var/tmp/ovirt-engine/config/%s" % filename,
r"(.*)",
r"********"
)
self.do_file_sub(
"/etc/ovirt-engine/redhatsupportplugin.conf",
r"proxyPassword=(.*)",
r"proxyPassword=********"
)
passwd_files = [
"logcollector.conf",
"imageuploader.conf",
"isouploader.conf"
]
for conf_file in passwd_files:
conf_path = os.path.join("/etc/ovirt-engine", conf_file)
self.do_file_sub(
conf_path,
r"passwd=(.*)",
r"passwd=********"
)
self.do_file_sub(
conf_path,
r"pg-pass=(.*)",
r"pg-pass=********"
)
sensitive_keys = self.DEFAULT_SENSITIVE_KEYS
# Handle --alloptions case which set this to True.
keys_opt = self.get_option('sensitive_keys')
if keys_opt and keys_opt is not True:
sensitive_keys = keys_opt
key_list = [x for x in sensitive_keys.split(':') if x]
for key in key_list:
self.do_path_regex_sub(
self.DB_PASS_FILES,
r'{key}=(.*)'.format(key=key),
r'{key}=********'.format(key=key)
)
# Answer files contain passwords
for key in (
'OVESETUP_CONFIG/adminPassword',
'OVESETUP_CONFIG/remoteEngineHostRootPassword',
'OVESETUP_DWH_DB/password',
'OVESETUP_DB/password',
'OVESETUP_REPORTS_CONFIG/adminPassword',
'OVESETUP_REPORTS_DB/password',
):
self.do_path_regex_sub(
r'/var/lib/ovirt-engine/setup/answers/.*',
r'{key}=(.*)'.format(key=key),
r'{key}=********'.format(key=key)
)
# aaa profiles contain passwords
protect_keys = [
"vars.password",
"pool.default.auth.simple.password",
"pool.default.ssl.truststore.password"
]
regexp = r"((?m)^\s*#*(%s)\s*=\s*)(.*)" % "|".join(protect_keys)
self.do_path_regex_sub("/etc/ovirt-engine/aaa/.*\.properties", regexp,
r"\1*********")
# vim: expandtab tabstop=4 shiftwidth=4
sosreport-3.2+git276-g7da50d6/sos/plugins/veritas.py 0000644 0001750 0001750 00000003173 12625313241 022024 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin
import os
class Veritas(Plugin, RedHatPlugin):
"""Veritas software
"""
plugin_name = 'veritas'
profiles = ('cluster', 'storage')
# Information about VRTSexplorer obtained from
# http://seer.entsupport.symantec.com/docs/243150.htm
option_list = [("script", "Define VRTSexplorer script path", "",
"/opt/VRTSspt/VRTSexplorer")]
def check_enabled(self):
return os.path.isfile(self.get_option("script"))
def setup(self):
""" interface with vrtsexplorer to capture veritas related data """
r = self.call_ext_prog(self.get_option("script"))
if r['status'] == 0:
tarfile = ""
for line in r['output']:
line = line.strip()
tarfile = self.do_regex_find_all(r"ftp (.*tar.gz)", line)
if len(tarfile) == 1:
self.add_copy_spec(tarfile[0])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/openstack_horizon.py 0000644 0001750 0001750 00000005753 12625313247 024122 0 ustar caribou caribou # Copyright (C) 2009 Red Hat, Inc., Joey Boggs
# Copyright (C) 2012 Rackspace US, Inc.,
# Justin Shepherd
# Copyright (C) 2013 Red Hat, Inc., Jeremy Agee
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class OpenStackHorizon(Plugin):
"""OpenStack Horizon
"""
plugin_name = "openstack_horizon"
profiles = ('openstack', 'openstack_controller')
option_list = []
def setup(self):
self.limit = self.get_option("log_size")
if self.get_option("all_logs"):
self.add_copy_spec_limit("/var/log/horizon/",
sizelimit=self.limit)
else:
self.add_copy_spec_limit("/var/log/horizon/*.log",
sizelimit=self.limit)
self.add_copy_spec("/etc/openstack-dashboard/")
def postproc(self):
protect_keys = [
"SECRET_KEY", "EMAIL_HOST_PASSWORD"
]
regexp = r"((?m)^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys)
self.do_path_regex_sub("/etc/openstack-dashboard/.*\.json",
regexp, r"\1*********")
self.do_path_regex_sub("/etc/openstack-dashboard/local_settings",
regexp, r"\1*********")
class DebianHorizon(OpenStackHorizon, DebianPlugin):
packages = (
'python-django-horizon',
'openstack-dashboard',
'openstack-dashboard-apache'
)
def setup(self):
super(DebianHorizon, self).setup()
self.add_copy_spec("/etc/apache2/sites-available/")
class UbuntuHorizon(OpenStackHorizon, UbuntuPlugin):
packages = (
'python-django-horizon',
'openstack-dashboard',
'openstack-dashboard-ubuntu-theme'
)
def setup(self):
super(UbuntuHorizon, self).setup()
self.add_copy_spec("/etc/apache2/conf.d/openstack-dashboard.conf")
class RedHatHorizon(OpenStackHorizon, RedHatPlugin):
packages = (
'python-django-horizon',
'openstack-dashboard'
)
def setup(self):
super(RedHatHorizon, self).setup()
self.add_copy_spec("/etc/httpd/conf.d/openstack-dashboard.conf")
if self.get_option("log"):
self.add_copy_spec("/var/log/httpd/")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/anacron.py 0000644 0001750 0001750 00000002116 12625313241 021764 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Anacron(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
"""Anacron job scheduling service"""
plugin_name = 'anacron'
profiles = ('system',)
# anacron may be provided by anacron, cronie-anacron etc.
# just look for the configuration file which is common
files = ('/etc/anacrontab',)
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/hpasm.py 0000644 0001750 0001750 00000002364 12625313241 021460 0 ustar caribou caribou # Copyright (C) 2014 Red Hat, Inc. Bryn M. Reeves
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Hpasm(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
"""HP Advanced Server Management
"""
plugin_name = 'hpasm'
profiles = ('system', 'hardware')
packages = ('hp-health',)
def setup(self):
self.add_copy_spec("/var/log/hp-health/hpasmd.log")
self.add_cmd_output([
"hpasmcli -s 'show asr'",
"hpasmcli -s 'show server'"
], timeout=0)
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/acpid.py 0000644 0001750 0001750 00000002273 12625313241 021427 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Acpid(Plugin):
"""ACPI daemon information"""
plugin_name = "acpid"
profiles = ('hardware',)
class RedHatAcpid(Acpid, RedHatPlugin):
def setup(self):
self.add_copy_spec([
"/var/log/acpid*",
"/etc/acpi/events/power.conf"])
class DebianAcpid(Acpid, DebianPlugin, UbuntuPlugin):
def setup(self):
self.add_copy_spec([
"/etc/acpi/events/powerbtn*"])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/lightdm.py 0000644 0001750 0001750 00000003452 12625313241 021777 0 ustar caribou caribou # Copyright (C) 2015 Red Hat, Inc., Bryn M. Reeves
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class LightDm(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
"""Light Display Manager
"""
packages = ('lightdm', )
profiles = ('desktop', )
plugin_name = 'lightdm'
def setup(self):
self.add_cmd_output([
"journalctl -u lightdm",
"systemctl status lightdm.service"
])
self.add_copy_spec([
"/etc/lightdm/lightdm.conf",
"/etc/lightdm/users.conf"
])
if not self.get_option("all_logs"):
limit = self.get_option("log_size")
self.add_copy_spec_limit("/var/log/lightdm/lightdm.log",
sizelimit=limit)
self.add_copy_spec_limit("/var/log/lightdm/x-0-greeter.log",
sizelimit=limit)
self.add_copy_spec_limit("/var/log/lightdm/x-0.log",
sizelimit=limit)
else:
self.add_copy_spec("/var/log/lightdm")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/insights.py 0000644 0001750 0001750 00000003041 12625313247 022177 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin
class RedHatAccessInsights(Plugin, RedHatPlugin):
'''Collect config and log for Red Hat Access Insights
'''
plugin_name = 'insights'
packages = ['redhat-access-insights']
profiles = ('system', 'sysmgmt')
conf_file = '/etc/redhat-access-insights/redhat-access-insights.conf'
def setup(self):
log_size = self.get_option('log_size')
self.add_copy_spec(self.conf_file)
self.add_copy_spec_limit('/var/log/redhat-access-insights/*.log',
sizelimit=log_size)
def postproc(self):
self.do_file_sub(
self.conf_file,
r'(password[\t\ ]*=[\t\ ]*)(.+)',
r'\1********'
)
self.do_file_sub(
self.conf_file,
r'(proxy[\t\ ]*=.*)(:)(.*)(@.*)',
r'\1\2********\4'
)
sosreport-3.2+git276-g7da50d6/sos/plugins/puppet.py 0000644 0001750 0001750 00000002606 12625313241 021664 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
from glob import glob
class Puppet(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
"""Puppet service
"""
plugin_name = 'puppet'
profiles = ('services',)
def setup(self):
self.add_copy_spec([
"/etc/puppet/*.conf",
"/etc/puppet/rack/*",
"/etc/puppet/manifests/*",
"/var/log/puppet/*.log",
])
def postproc(self):
for device_conf in glob("/etc/puppet/device.conf*"):
self.do_file_sub(
device_conf,
r"(.*url*.ssh://.*:).*(@.*)",
r"\1%s\2" % ('***')
)
return
# vim: et ts=4 sw=4
sosreport-3.2+git276-g7da50d6/sos/plugins/ppp.py 0000644 0001750 0001750 00000002303 12625313241 021140 0 ustar caribou caribou # Copyright (C) 2007 Sadique Puthen
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Ppp(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
"""Point-to-point protocol
"""
plugin_name = 'ppp'
profiles = ('system', 'network')
packages = ('ppp',)
def setup(self):
self.add_copy_spec([
"/etc/wvdial.conf",
"/etc/ppp",
"/var/log/ppp"
])
self.add_cmd_output("adsl-status")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/landscape.py 0000644 0001750 0001750 00000006062 12625313241 022301 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, UbuntuPlugin
class Landscape(Plugin, UbuntuPlugin):
"""Ubuntu Landscape client
"""
plugin_name = 'landscape'
profiles = ('sysmgmt',)
files = ('/etc/landscape/client.conf', '/etc/landscape/service.conf')
packages = ('landscape-client', 'landscape-server')
def setup(self):
self.add_copy_spec("/etc/landscape/client.conf")
self.add_copy_spec("/etc/default/landscape-client")
self.add_copy_spec("/etc/landscape/service.conf")
self.add_copy_spec("/etc/landscape/service.conf.old")
self.add_copy_spec("/etc/default/landscape-server")
if not self.get_option("all_logs"):
limit = self.get_option("log_size")
self.add_copy_spec_limit("/var/log/landscape/*.log",
sizelimit=limit)
self.add_copy_spec_limit("/var/log/landscape-server/*.log",
sizelimit=limit)
else:
self.add_copy_spec("/var/log/landscape")
self.add_copy_spec("/var/log/landscape-server")
self.add_cmd_output("gpg --verify /etc/landscape/license.txt")
self.add_cmd_output("head -n 5 /etc/landscape/license.txt")
self.add_cmd_output("lsctl status")
def postproc(self):
self.do_file_sub(
"/etc/landscape/client.conf",
r"registration_password(.*)",
r"registration_password[********]"
)
self.do_file_sub(
"/etc/landscape/service.conf",
r"password = (.*)",
r"password = [********]"
)
self.do_file_sub(
"/etc/landscape/service.conf",
r"store_password = (.*)",
r"store_password = [********]"
)
self.do_file_sub(
"/etc/landscape/service.conf",
r"secret-token = (.*)",
r"secret-token = [********]"
)
self.do_file_sub(
"/etc/landscape/service.conf.old",
r"password = (.*)",
r"password = [********]"
)
self.do_file_sub(
"/etc/landscape/service.conf.old",
r"store_password = (.*)",
r"store_password = [********]"
)
self.do_file_sub(
"/etc/landscape/service.conf.old",
r"secret-token = (.*)",
r"secret-token = [********]"
)
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/ds.py 0000644 0001750 0001750 00000005565 12625313241 020764 0 ustar caribou caribou # Copyright (C) 2007 Red Hat, Inc., Kent Lamb
# Copyright (C) 2014 Red Hat, Inc., Bryn M. Reeves
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin
import os
class DirectoryServer(Plugin, RedHatPlugin):
"""Directory Server
"""
plugin_name = 'directoryserver'
profiles = ('identity',)
files = ('/etc/dirsrv', '/opt/redhat-ds')
packages = ('redhat-ds-base', 'redhat-ds-7')
def check_version(self):
if self.is_installed("redhat-ds-base") or \
os.path.exists("/etc/dirsrv"):
return "ds8"
elif self.is_installed("redhat-ds-7") or \
os.path.exists("/opt/redhat-ds"):
return "ds7"
return False
def setup(self):
self.add_forbidden_path("/etc/dirsrv/slapd*/pin.txt")
self.add_forbidden_path("/etc/dirsrv/slapd*/key3.db")
self.add_forbidden_path("/etc/dirsrv/slapd*/pwfile.txt")
self.add_forbidden_path("/etc/dirsrv/slapd*/*passw*")
self.add_forbidden_path("/etc/dirsrv/admin-serv/key3.db")
self.add_forbidden_path("/etc/dirsrv/admin-serv/admpw")
self.add_forbidden_path("/etc/dirsrv/admin-serv/password.conf")
try:
for d in os.listdir("/etc/dirsrv"):
if d[0:5] == 'slapd':
certpath = os.path.join("/etc/dirsrv", d)
self.add_cmd_output("certutil -L -d %s" % certpath)
except:
self._log_warn("could not list /etc/dirsrv")
if not self.check_version():
self.add_alert("Directory Server not found.")
elif "ds8" in self.check_version():
self.add_copy_spec([
"/etc/dirsrv/slapd*/cert8.db",
"/etc/dirsrv/slapd*/certmap.conf",
"/etc/dirsrv/slapd*/dse.ldif",
"/etc/dirsrv/slapd*/dse.ldif.startOK",
"/etc/dirsrv/slapd*/secmod.db",
"/etc/dirsrv/slapd*/schema/*.ldif",
"/var/log/dirsrv/*"
])
elif "ds7" in self.check_version():
self.add_copy_spec([
"/opt/redhat-ds/slapd-*/config",
"/opt/redhat-ds/slapd-*/logs"
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/nscd.py 0000644 0001750 0001750 00000002617 12625313241 021300 0 ustar caribou caribou # Copyright (C) 2007 Shijoe George
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Nscd(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
"""Name service caching daemon
"""
plugin_name = 'nscd'
profiles = ('services', 'identity', 'system')
files = ('/etc/nscd.conf',)
packages = ('nscd',)
def setup(self):
self.add_copy_spec("/etc/nscd.conf")
opt = self.file_grep(r"^\s*logfile", "/etc/nscd.conf")
if (len(opt) > 0):
for o in opt:
f = o.split()
self.add_copy_spec_limit(f[1],
sizelimit=self.get_option("log_size"))
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/docker.py 0000644 0001750 0001750 00000004600 12625313247 021620 0 ustar caribou caribou # Copyright (C) 2014 Red Hat, Inc. Bryn M. Reeves
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, UbuntuPlugin
class Docker(Plugin):
"""Docker containers
"""
plugin_name = 'docker'
profiles = ('virt',)
docker_bin = "docker"
option_list = [("all", "capture all container logs even the "
"terminated ones", 'fast', False)]
def setup(self):
self.add_copy_spec([
"/var/lib/docker/repositories-*"
])
self.add_cmd_output([
"journalctl -u docker",
"{0} info".format(self.docker_bin),
"{0} ps".format(self.docker_bin),
"{0} images".format(self.docker_bin)
])
ps_cmd = "{0} ps".format(self.docker_bin)
if self.get_option('all'):
ps_cmd = "{0} -a".format(ps_cmd)
result = self.get_command_output(ps_cmd)
if result['status'] == 0:
for line in result['output'].splitlines()[1:]:
container_id = line.split(" ")[0]
self.add_cmd_output([
"{0} logs {1}".format(self.docker_bin, container_id)
])
class RedHatDocker(Docker, RedHatPlugin):
packages = ('docker', 'docker-io')
def setup(self):
super(RedHatDocker, self).setup()
self.add_copy_spec([
"/etc/udev/rules.d/80-docker.rules"
])
class UbuntuDocker(Docker, UbuntuPlugin):
packages = ('docker.io',)
# Name collision with another package requires docker binary rename
docker_bin = 'docker.io'
def setup(self):
super(UbuntuDocker, self).setup()
self.add_copy_spec([
"/etc/default/docker.io"
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/devicemapper.py 0000644 0001750 0001750 00000002165 12625313241 023013 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class DeviceMapper(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
"""device-mapper framework
"""
plugin_name = 'devicemapper'
profiles = ('storage',)
def setup(self):
self.add_cmd_output([
"dmsetup info -c",
"dmsetup table",
"dmsetup status",
"dmsetup ls --tree"
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/services.py 0000644 0001750 0001750 00000003574 12625313241 022177 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Services(Plugin):
"""System services
"""
plugin_name = "services"
profiles = ('system', 'boot')
option_list = [("servicestatus", "get a status of all running services",
"slow", False)]
def setup(self):
self.add_copy_spec([
"/etc/inittab",
"/etc/rc.d"
])
if self.get_option('servicestatus'):
self.add_cmd_output("/sbin/service --status-all")
self.add_cmd_output([
"/sbin/runlevel",
"ls /var/lock/subsys"
])
class RedHatServices(Services, RedHatPlugin):
def setup(self):
super(RedHatServices, self).setup()
self.add_cmd_output("/sbin/chkconfig --list", root_symlink="chkconfig")
class DebianServices(Services, DebianPlugin, UbuntuPlugin):
def setup(self):
super(DebianServices, self).setup()
self.add_copy_spec("/etc/rc*.d")
self.add_cmd_output("/sbin/initctl show-config",
root_symlink="initctl")
if self.get_option('servicestatus'):
self.add_cmd_output("/sbin/initctl list")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/pam.py 0000644 0001750 0001750 00000002743 12625313241 021126 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Pam(Plugin):
"""Pluggable Authentication Modules
"""
plugin_name = "pam"
profiles = ('security', 'identity', 'system')
security_libs = ""
def setup(self):
self.add_copy_spec([
"/etc/pam.d",
"/etc/security"
])
self.add_cmd_output([
"ls -lanF %s" % self.security_libs,
"pam_tally2",
"faillock"
])
class RedHatPam(Pam, RedHatPlugin):
security_libs = "/lib*/security"
def setup(self):
super(RedHatPam, self).setup()
class DebianPam(Pam, DebianPlugin, UbuntuPlugin):
security_libs = "/lib/x86_64-linux-gnu/security"
def setup(self):
super(DebianPam, self).setup()
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/openstack_trove.py 0000644 0001750 0001750 00000004247 12625313247 023566 0 ustar caribou caribou # Copyright (C) 2015 Red Hat, Inc., Lee Yarwood
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class OpenStackTrove(Plugin):
"""OpenStack Trove
"""
plugin_name = "openstack_trove"
profiles = ('openstack', 'openstack_controller')
option_list = []
def setup(self):
self.limit = self.get_option("log_size")
if self.get_option("all_logs"):
self.add_copy_spec_limit("/var/log/trove/",
sizelimit=self.limit)
else:
self.add_copy_spec_limit("/var/log/trove/*.log",
sizelimit=self.limit)
self.add_copy_spec('/etc/trove/')
def postproc(self):
protect_keys = [
"default_password_length", "notifier_queue_password",
"rabbit_password", "replication_password", "connection",
"admin_password", "dns_passkey"
]
regexp = r"((?m)^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys)
self.do_path_regex_sub("/etc/trove/*", regexp, r"\1*********")
class DebianTrove(OpenStackTrove, DebianPlugin, UbuntuPlugin):
packages = [
'python-trove',
'trove-common',
'trove-api',
'trove-taskmanager'
]
def setup(self):
super(DebianTrove, self).setup()
class RedHatTrove(OpenStackTrove, RedHatPlugin):
packages = ['openstack-trove']
def setup(self):
super(RedHatTrove, self).setup()
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/processor.py 0000644 0001750 0001750 00000002644 12625313241 022370 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, UbuntuPlugin, DebianPlugin
class Processor(Plugin, RedHatPlugin, UbuntuPlugin, DebianPlugin):
"""CPU information
"""
plugin_name = 'processor'
profiles = ('system', 'hardware', 'memory')
files = ('/proc/cpuinfo',)
packages = ('cpufreq-utils')
def setup(self):
self.add_copy_spec([
"/proc/cpuinfo",
"/sys/class/cpuid",
"/sys/devices/system/cpu"
])
self.add_cmd_output([
"lscpu",
"cpupower info",
"cpupower idle-info",
"cpupower frequency-info"
])
if '86' in self.policy().get_arch():
self.add_cmd_output("x86info -a")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/manageiq.py 0000644 0001750 0001750 00000006447 12625313241 022140 0 ustar caribou caribou # -*- python -*-
# -*- coding: utf-8 -*-
# Copyright (C) 2015 Red Hat, Inc., Pep Turró Mauri
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin
import os.path
class ManageIQ(Plugin, RedHatPlugin):
"""ManageIQ/CloudForms related information
"""
plugin_name = 'manageiq'
miq_dir = '/var/www/miq/vmdb'
packages = ('cfme',)
files = (
os.path.join(miq_dir, 'BUILD'),
os.path.join(miq_dir, 'GUID'),
os.path.join(miq_dir, 'VERSION')
)
# Config files to collect from miq_dir/config/
miq_conf_dir = os.path.join(miq_dir, "config")
miq_conf_files = [
'application.rb',
'boot.rb',
'environment.rb',
'preinitializer.rb',
'routes.rb',
'environments/metric_fu.rb',
'environments/production.rb',
'api.yml',
'broker_notify_properties.tmpl.yml',
'capacity.tmpl.yml',
'dashboard.yml',
'event_handling.tmpl.yml',
'hostdefaults.tmpl.yml',
'mongrel_cluster.yml',
'mongrel_win.yml',
'storage.tmpl.yml',
'vmdb.tmpl.yml',
'vmdb.yml.db',
'event_handling.yml.db',
'lighttpd.conf',
'replication.conf'
]
# Log files to collect from miq_dir/log/
miq_log_dir = os.path.join(miq_dir, "log")
miq_log_files = [
'appliance_console.log',
'api.log',
'audit.log',
'automation.log',
'aws.log',
'evm.log',
'fog.log',
'miq_ntpdate.log',
'mongrel.log',
'policy.log',
'prince.log',
'production.log',
'rhevm.log',
'scvmm.log',
'top_output.log',
'vim.log',
'vmdb_restart.log',
'vmstat_output.log',
'vmstat_output.log',
'apache/miq_apache.log',
'apache/ssl_access.log',
'apache/ssl_error.log',
'apache/ssl_request.log',
'apache/ssl_mirror_request.log',
'apache/ssl_mirror_error.log',
'apache/ssl_mirror_access_error.log',
'gem_list.txt',
'last_startup.txt',
'package_list_rpm.txt',
'vendor_gems.txt'
]
def setup(self):
if self.get_option("all_logs"):
# turn all log files to a glob to include logrotated ones
self.miq_log_files = map(lambda x: x + '*', self.miq_log_files)
self.add_copy_spec(list(self.files))
self.add_copy_spec([
os.path.join(self.miq_conf_dir, x) for x in self.miq_conf_files
])
self.add_copy_spec([
os.path.join(self.miq_log_dir, x) for x in self.miq_log_files
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/oddjob.py 0000644 0001750 0001750 00000002254 12625313241 021607 0 ustar caribou caribou # Copyright (C) 2007 Sadique Puthen
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin
class Oddjob(Plugin, RedHatPlugin):
"""OddJob task scheduler
"""
plugin_name = 'oddjob'
profiles = ('services', 'sysmgmt')
files = ('/etc/oddjobd.conf',)
packages = ('oddjob',)
def setup(self):
self.add_copy_spec([
"/etc/oddjobd.conf",
"/etc/oddjobd.conf.d",
"/etc/dbus-1/system.d/oddjob.conf"
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/pacemaker.py 0000644 0001750 0001750 00000002206 12435106710 022273 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Pacemaker(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
"HA Cluster resource manager"
plugin_name = "pacemaker"
profiles = ("cluster", )
packages = ("pacemaker", )
def setup(self):
self.add_copy_spec([
"/var/lib/pacemaker/cib/cib.xml"
])
self.add_cmd_output([
"crm status",
"crm configure show",
])
sosreport-3.2+git276-g7da50d6/sos/plugins/apport.py 0000644 0001750 0001750 00000003441 12625313241 021652 0 ustar caribou caribou # Copyright (c) 2012 Adam Stokes
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, DebianPlugin, UbuntuPlugin
class Apport(Plugin, DebianPlugin, UbuntuPlugin):
"""Apport crash reporting tool
"""
plugin_name = 'apport'
profiles = ('debug',)
def setup(self):
if not self.get_option("all_logs"):
limit = self.get_option("log_size")
self.add_copy_spec_limit("/var/log/apport.log",
sizelimit=limit)
self.add_copy_spec_limit("/var/log/apport.log.1",
sizelimit=limit)
else:
self.add_copy_spec("/var/log/apport*")
self.add_copy_spec("/etc/apport/*")
self.add_copy_spec("/var/lib/whoopsie/whoopsie-id")
self.add_cmd_output(
"gdbus call -y -d com.ubuntu.WhoopsiePreferences \
-o /com/ubuntu/WhoopsiePreferences \
-m com.ubuntu.WhoopsiePreferences.GetIdentifier")
self.add_cmd_output("ls -alh /var/crash/")
self.add_cmd_output("bash -c 'grep -B 50 -m 1 ProcMaps /var/crash/*'")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/nis.py 0000644 0001750 0001750 00000002161 12625313241 021134 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Nis(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
"""Network information service
"""
plugin_name = 'nis'
profiles = ('identity', 'services')
files = ('/var/yp',)
def setup(self):
self.add_copy_spec([
"/etc/yp*.conf",
"/var/yp/*"
])
self.add_cmd_output("domainname")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/dovecot.py 0000644 0001750 0001750 00000002702 12625313241 022007 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Dovecot(Plugin):
"""Dovecot IMAP and POP3
"""
plugin_name = "dovecot"
profiles = ('mail',)
def setup(self):
self.add_copy_spec("/etc/dovecot*")
self.add_cmd_output("dovecot -n")
class RedHatDovecot(Dovecot, RedHatPlugin):
"""dovecot server related information
"""
def setup(self):
super(RedHatDovecot, self).setup()
packages = ('dovecot', )
files = ('/etc/dovecot.conf',)
class DebianDovecot(Dovecot, DebianPlugin, UbuntuPlugin):
"""dovecot server related information for Debian based distribution
"""
def setup(self):
super(DebianDovecot, self).setup()
files = ('/etc/dovecot/README',)
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/targetcli.py 0000644 0001750 0001750 00000002450 12625313241 022322 0 ustar caribou caribou # Copyright (C) 2015 Red Hat, Inc., Bryn M. Reeves
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class TargetCli(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
"""TargetCLI TCM/LIO configuration
"""
packages = ('targetcli', 'python-rtslib')
profiles = ('storage', )
plugin_name = 'targetcli'
def setup(self):
self.add_cmd_output([
"targetcli ls",
"targetcli status",
"journalctl -u target",
"systemctl status target.service"
])
self.add_copy_spec("/etc/target")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/openstack_nova.py 0000644 0001750 0001750 00000012261 12625313247 023365 0 ustar caribou caribou # Copyright (C) 2009 Red Hat, Inc., Joey Boggs
# Copyright (C) 2012 Rackspace US, Inc.,
# Justin Shepherd
# Copyright (C) 2013 Red Hat, Inc., Jeremy Agee
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class OpenStackNova(Plugin):
"""OpenStack Nova
"""
plugin_name = "openstack_nova"
profiles = ('openstack', 'openstack_controller', 'openstack_compute')
option_list = [("cmds", "gathers openstack nova commands", "slow", False)]
def setup(self):
if self.get_option("cmds"):
self.add_cmd_output(
"nova-manage config list",
suggest_filename="nova_config_list")
self.add_cmd_output(
"nova-manage service list",
suggest_filename="nova_service_list")
self.add_cmd_output(
"nova-manage db version",
suggest_filename="nova_db_version")
self.add_cmd_output(
"nova-manage fixed list",
suggest_filename="nova_fixed_ip_list")
self.add_cmd_output(
"nova-manage floating list",
suggest_filename="nova_floating_ip_list")
self.add_cmd_output(
"nova-manage flavor list",
suggest_filename="nova_flavor_list")
self.add_cmd_output(
"nova-manage network list",
suggest_filename="nova_network_list")
self.add_cmd_output(
"nova-manage vm list",
suggest_filename="nova_vm_list")
self.limit = self.get_option("log_size")
if self.get_option("all_logs"):
self.add_copy_spec_limit("/var/log/nova/",
sizelimit=self.limit)
else:
self.add_copy_spec_limit("/var/log/nova/*.log",
sizelimit=self.limit)
self.add_copy_spec("/etc/nova/")
def postproc(self):
protect_keys = [
"ldap_dns_password", "neutron_admin_password", "rabbit_password",
"qpid_password", "powervm_mgr_passwd", "virtual_power_host_pass",
"xenapi_connection_password", "password", "host_password",
"vnc_password", "connection", "sql_connection", "admin_password",
"connection_password", "memcache_secret_key", "s3_secret_key",
"metadata_proxy_shared_secret"
]
regexp = r"((?m)^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys)
self.do_path_regex_sub("/etc/nova/*", regexp, r"\1*********")
class DebianNova(OpenStackNova, DebianPlugin, UbuntuPlugin):
nova = False
packages = (
'nova-api-ec2',
'nova-api-metadata',
'nova-api-os-compute',
'nova-api-os-volume',
'nova-common',
'nova-compute',
'nova-compute-kvm',
'nova-compute-lxc',
'nova-compute-qemu',
'nova-compute-uml',
'nova-compute-xcp',
'nova-compute-xen',
'nova-xcp-plugins',
'nova-consoleauth',
'nova-network',
'nova-scheduler',
'nova-volume',
'novnc',
'python-nova',
'python-novaclient',
'python-novnc'
)
def check_enabled(self):
self.nova = self.is_installed("nova-common")
return self.nova
def setup(self):
super(DebianNova, self).setup()
self.add_copy_spec(["/etc/sudoers.d/nova_sudoers"])
class RedHatNova(OpenStackNova, RedHatPlugin):
nova = False
packages = (
'openstack-nova-common',
'openstack-nova-network',
'openstack-nova-conductor',
'openstack-nova-conductor',
'openstack-nova-scheduler',
'openstack-nova-console',
'openstack-nova-novncproxy',
'openstack-nova-compute',
'openstack-nova-api',
'openstack-nova-cert',
'openstack-nova-cells',
'openstack-nova-objectstore',
'python-nova',
'python-novaclient',
'novnc'
)
def check_enabled(self):
self.nova = self.is_installed("openstack-nova-common")
return self.nova
def setup(self):
super(RedHatNova, self).setup()
self.add_copy_spec([
"/etc/logrotate.d/openstack-nova",
"/etc/polkit-1/localauthority/50-local.d/50-nova.pkla",
"/etc/sudoers.d/nova",
"/etc/security/limits.d/91-nova.conf",
"/etc/sysconfig/openstack-nova-novncproxy"
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/vsftpd.py 0000644 0001750 0001750 00000002031 12625313241 021645 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin
class Vsftpd(Plugin, RedHatPlugin):
"""Vsftpd server
"""
plugin_name = 'vsftpd'
profiles = ('services',)
files = ('/etc/vsftpd',)
packages = ('vsftpd',)
def setup(self):
self.add_copy_spec([
"/etc/ftp*",
"/etc/vsftpd"
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/dhcp.py 0000644 0001750 0001750 00000002577 12625313241 021274 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, UbuntuPlugin
class Dhcp(Plugin):
"""DHCP daemon
"""
plugin_name = "dhcp"
profiles = ('network',)
class RedHatDhcp(Dhcp, RedHatPlugin):
files = ('/etc/rc.d/init.d/dhcpd',)
packages = ('dhcp',)
def setup(self):
super(RedHatDhcp, self).setup()
self.add_copy_spec([
"/etc/dhcpd.conf",
"/etc/dhcp"
])
class UbuntuDhcp(Dhcp, UbuntuPlugin):
files = ('/etc/init.d/udhcpd',)
packages = ('udhcpd',)
def setup(self):
super(UbuntuDhcp, self).setup()
self.add_copy_spec([
"/etc/default/udhcpd",
"/etc/udhcpd.conf"
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/maas.py 0000644 0001750 0001750 00000004744 12625313241 021275 0 ustar caribou caribou # Copyright (C) 2013 Adam Stokes
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, UbuntuPlugin
class Maas(Plugin, UbuntuPlugin):
"""Ubuntu Metal-As-A-Service
"""
plugin_name = 'maas'
profiles = ('sysmgmt',)
option_list = [
('profile-name',
'The name with which you will later refer to this remote', '', False),
('url', 'The URL of the remote API', '', False),
('credentials',
'The credentials, also known as the API key', '', False)
]
def _has_login_options(self):
return self.get_option("url") and self.get_option("credentials") \
and self.get_option("profile-name")
def _remote_api_login(self):
ret = self.call_ext_prog("maas login %s %s %s" % (
self.get_option("profile-name"),
self.get_option("url"),
self.get_option("credentials")))
return ret['status'] == 0
def setup(self):
self.add_copy_spec([
"/etc/squid-deb-proxy",
"/etc/maas",
"/var/lib/maas/dhcp*",
"/var/log/apache2*",
"/var/log/maas*",
"/var/log/upstart/maas-*",
])
self.add_cmd_output([
"apt-cache policy maas-*",
"apt-cache policy python-django-*",
])
if self.is_installed("maas-region-controller"):
self.add_cmd_output([
"maas-region-admin dumpdata",
])
if self._has_login_options():
if self._remote_api_login():
self.add_cmd_output("maas %s commissioning-results list" %
self.get_option("profile-name"))
else:
self._log_error(
"Cannot login into MAAS remote API with provided creds.")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/md.py 0000644 0001750 0001750 00000002161 12625313241 020743 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Md(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
"""MD RAID subsystem
"""
plugin_name = 'md'
profiles = ('storage',)
def setup(self):
self.add_cmd_output("mdadm -D /dev/md*")
self.add_copy_spec([
"/proc/mdstat",
"/etc/mdadm.conf",
"/dev/md/md-device-map"
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/tuned.py 0000644 0001750 0001750 00000002575 12625313241 021473 0 ustar caribou caribou # Copyright (C) 2014 Red Hat, Inc., Peter Portante
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin
class Tuned(Plugin, RedHatPlugin):
"""Tuned system tuning daemon
"""
packages = ('tuned',)
profiles = ('system', 'performance')
plugin_name = 'tuned'
def setup(self):
self.add_cmd_output([
"tuned-adm list",
"tuned-adm active",
"tuned-adm recommend"
])
self.add_copy_spec([
"/etc/tuned.conf",
"/etc/tune-profiles"
])
self.add_copy_spec([
"/etc/tuned",
"/usr/lib/tuned",
"/var/log/tuned/tuned.log"
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/mysql.py 0000644 0001750 0001750 00000006510 12625313241 021512 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
import os
class Mysql(Plugin):
"""MySQL and MariaDB RDBMS
"""
plugin_name = "mysql"
profiles = ('services',)
mysql_cnf = "/etc/my.cnf"
pw_warn_text = " (password visible in process listings)"
option_list = [
("dbuser", "username for database dumps", "", "mysql"),
("dbpass", "password for database dumps" + pw_warn_text, "", False),
("dbdump", "collect a database dump", "", False)
]
def setup(self):
super(Mysql, self).setup()
self.add_copy_spec([
self.mysql_cnf,
# Required for MariaDB under pacemaker (MariaDB-Galera)
"/var/log/mysqld.log",
"/var/log/mysql/mysqld.log",
"/var/log/mariadb/mariadb.log",
])
if self.get_option("all_logs"):
self.add_copy_spec([
"/var/log/mysql*",
"/var/log/mariadb*"
])
if self.get_option("dbdump"):
msg = "database user name and password must be supplied"
dbdump_err = "mysql.dbdump: %s" % msg
dbuser = self.get_option("dbuser")
dbpass = self.get_option("dbpass")
if 'MYSQL_PWD' in os.environ:
dbpass = os.environ['MYSQL_PWD']
if dbuser is True or dbpass is True:
# sosreport -a or -k mysql.{dbuser,dbpass}
self.soslog.warning(dbdump_err)
return
if not dbpass or dbpass is False:
# no MySQL password
self.soslog.warning(dbdump_err)
return
# no need to save/restore as this variable is private to
# the mysql plugin.
os.environ['MYSQL_PWD'] = dbpass
opts = "--user=%s --all-databases" % dbuser
name = "mysqldump_--all-databases"
self.add_cmd_output("mysqldump %s" % opts, suggest_filename=name)
class RedHatMysql(Mysql, RedHatPlugin):
packages = (
'mysql-server',
'mysql',
'mariadb-server',
'mariadb'
)
def setup(self):
super(RedHatMysql, self).setup()
self.add_copy_spec([
"/etc/ld.so.conf.d/mysql-*.conf",
"/etc/ld.so.conf.d/mariadb-*.conf"
])
self.add_copy_spec("/etc/my.cnf.d/*")
class DebianMysql(Mysql, DebianPlugin, UbuntuPlugin):
packages = (
'mysql-server',
'mysql-common',
'mariadb-server',
'mariadb-common'
)
def setup(self):
super(DebianMysql, self).setup()
self.add_copy_spec("/etc/mysql/conf.d/mysql*")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/smartcard.py 0000644 0001750 0001750 00000002521 12625313241 022323 0 ustar caribou caribou # Copyright (C) 2007 Sadique Puthen
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin
class Smartcard(Plugin, RedHatPlugin):
"""PKCS#11 smart cards
"""
plugin_name = 'smartcard'
profiles = ('security', 'identity', 'hardware')
files = ('/etc/pam_pkcs11/pam_pkcs11.conf',)
packages = ('pam_pkcs11',)
def setup(self):
self.add_copy_spec([
"/etc/reader.conf",
"/etc/reader.conf.d/",
"/etc/pam_pkcs11/"])
self.add_cmd_output([
"pkcs11_inspect debug",
"pklogin_finder debug",
"ls -nl /usr/lib*/pam_pkcs11/"
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/named.py 0000644 0001750 0001750 00000005542 12625313241 021435 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
from os.path import exists, join, normpath
class Named(Plugin):
"""BIND named server
"""
plugin_name = "named"
profiles = ('system', 'services', 'network')
named_conf = "/etc/named.conf"
config_files = named_conf
def setup(self):
for cfg in self.config_files:
if exists(cfg):
self.add_copy_spec([
cfg,
self.get_dns_dir(cfg)
])
self.add_forbidden_path(join(self.get_dns_dir(cfg),
"chroot/dev"))
self.add_forbidden_path(join(self.get_dns_dir(cfg),
"chroot/proc"))
def get_dns_dir(self, config_file):
""" grab directory path from named{conf,boot}
"""
directory_list = self.do_regex_find_all("directory\s+\"(.*)\"",
config_file)
if directory_list:
return normpath(directory_list[0])
else:
return ""
def postproc(self):
match = r"(\s*arg \"password )[^\"]*"
subst = r"\1******"
self.do_file_sub(self.named_conf, match, subst)
class RedHatNamed(Named, RedHatPlugin):
named_conf = "/etc/named.conf"
config_files = ("/etc/named.conf",
"/etc/named.boot")
files = (named_conf, '/etc/sysconfig/named')
packages = ('bind',)
def setup(self):
super(RedHatNamed, self).setup()
self.add_copy_spec("/etc/named/")
self.add_copy_spec("/etc/sysconfig/named")
self.add_cmd_output("klist -ket /etc/named.keytab")
self.add_forbidden_path("/etc/named.keytab")
return
class DebianNamed(Named, DebianPlugin, UbuntuPlugin):
files = ('/etc/bind/named.conf')
packages = ('bind9',)
named_conf = "/etc/bind/named.conf"
config_files = (named_conf,
"/etc/bind/named.conf.options",
"/etc/bind/named.conf.local")
def setup(self):
super(DebianNamed, self).setup()
self.add_copy_spec("/etc/bind/")
return
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/quagga.py 0000644 0001750 0001750 00000002070 12625313241 021607 0 ustar caribou caribou # Copyright (C) 2007 Ranjith Rajaram
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin
class Quagga(Plugin, RedHatPlugin):
"""Quagga routing service
"""
plugin_name = 'quagga'
profiles = ('network',)
files = ('/etc/quagga/zebra.conf',)
packages = ('quagga',)
def setup(self):
self.add_copy_spec("/etc/quagga/")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/boot.py 0000644 0001750 0001750 00000003274 12625313241 021314 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
from glob import glob
class Boot(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
"""Bootloader information
"""
plugin_name = 'boot'
profiles = ('system', 'boot')
option_list = [
("all-images", "collect lsinitrd for all images", "slow", False)
]
def setup(self):
self.add_copy_spec([
# legacy / special purpose bootloader configs
"/etc/milo.conf",
"/etc/silo.conf",
"/boot/efi/efi/redhat/elilo.conf",
"/etc/yaboot.conf",
"/boot/yaboot.conf"
])
self.add_cmd_output([
"ls -lanR /boot",
"lsinitrd"
])
self.add_cmd_output("efibootmgr")
if self.get_option("all-images"):
for image in glob('/boot/initr*.img'):
if image[-9:] == "kdump.img":
continue
self.add_cmd_output("lsinitrd %s" % image)
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/tomcat.py 0000644 0001750 0001750 00000002602 12625313241 021632 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin
class Tomcat(Plugin, RedHatPlugin):
"""Apache Tomcat server
"""
plugin_name = 'tomcat'
profiles = ('webserver', 'java', 'services', 'sysmgmt')
packages = ('tomcat6', 'tomcat')
def setup(self):
self.add_copy_spec([
"/etc/tomcat",
"/etc/tomcat6"
])
limit = self.get_option("log_size")
log_glob = "/var/log/tomcat*/catalina.out"
self.add_copy_spec_limit(log_glob, sizelimit=limit)
def postproc(self):
self.do_path_regex_sub(
r"\/etc\/tomcat.*\/tomcat-users.xml",
r"password=(\S*)",
r'password="********"'
)
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/gluster.py 0000644 0001750 0001750 00000011305 12625313241 022030 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
import time
import os.path
import os
import string
from sos.plugins import Plugin, RedHatPlugin
class Gluster(Plugin, RedHatPlugin):
"""GlusterFS storage"""
plugin_name = 'gluster'
profiles = ('storage', 'virt')
statedump_dir = '/tmp/glusterfs-statedumps'
packages = ["glusterfs", "glusterfs-core"]
files = ["/etc/glusterd", "/var/lib/glusterd"]
def get_volume_names(self, volume_file):
"""Return a dictionary for which key are volume names according to the
output of gluster volume info stored in volume_file.
"""
out = []
fp = open(volume_file, 'r')
for line in fp.readlines():
if not line.startswith("Volume Name:"):
continue
volname = line[12:-1]
out.append(volname)
fp.close()
return out
def make_preparations(self, name_dir):
try:
os.mkdir(name_dir)
except:
pass
fp = open('/tmp/glusterdump.options', 'w')
data = 'path=' + name_dir + '\n'
fp.write(data)
fp.write('all=yes')
fp.close()
def wait_for_statedump(self, name_dir):
statedumps_present = 0
statedump_entries = os.listdir(name_dir)
for statedump_file in statedump_entries:
statedumps_present = statedumps_present+1
last_line = 'tmp'
ret = -1
while ret == -1:
last_line = file(
name_dir + '/' + statedump_file, "r").readlines()[-1]
ret = string.count(last_line, 'DUMP_END_TIME')
def postproc(self):
if not os.path.exists(self.statedump_dir):
return
try:
for dirs in os.listdir(self.statedump_dir):
os.remove(os.path.join(self.statedump_dir, dirs))
os.rmdir(self.statedump_dir)
os.unlink('/tmp/glusterdump.options')
except:
pass
def setup(self):
self.add_forbidden_path("/var/lib/glusterd/geo-replication/secret.pem")
self.add_cmd_output("gluster peer status")
self.add_copy_spec([
"/etc/redhat-storage-release",
# collect unified file and object storage configuration
"/etc/swift/",
# glusterfs-server rpm scripts stash this on migration to 3.3.x
"/etc/glusterd.rpmsave",
# common to all versions
"/etc/glusterfs",
"/var/lib/glusterd/",
"/var/log/glusterfs"
])
self.make_preparations(self.statedump_dir)
if self.check_ext_prog("killall -USR1 glusterfs glusterfsd"):
# let all the processes catch the signal and create statedump file
# entries.
time.sleep(1)
self.wait_for_statedump(self.statedump_dir)
self.add_copy_spec('/tmp/glusterdump.options')
self.add_copy_spec(self.statedump_dir)
else:
self.soslog.info("could not send SIGUSR1 to glusterfs processes")
volume_file = self.get_cmd_output_now("gluster volume info")
if volume_file:
for volname in self.get_volume_names(volume_file):
self.add_cmd_output([
"gluster volume geo-replication %s status"
% volname,
"gluster volume heal %s info" % volname,
"gluster volume heal %s info split-brain"
% volname,
"gluster snapshot list %s" % volname,
"gluster volume quota %s list" % volname,
"gluster volume rebalance %s status"
% volname,
"gluster snapshot info %s" % volname,
"gluster snapshot status %s" % volname])
self.add_cmd_output("gluster pool list")
self.add_cmd_output("gluster volume status")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/sar.py 0000644 0001750 0001750 00000005753 12625313241 021142 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
import os
class Sar(Plugin,):
"""System Activity Reporter
"""
plugin_name = 'sar'
profiles = ('system', 'performance')
packages = ('sysstat',)
sa_path = '/var/log/sa'
option_list = [("all_sar", "gather all system activity records",
"", False)]
# size-limit SAR data collected by default (MB)
sa_size = 20
def setup(self):
if self.get_option("all_sar"):
self.sa_size = 0
# Copy all sa??, sar??, sa??.* and sar??.* files, which will net
# compressed and uncompressed versions, typically.
for suffix in ('', '.*'):
self.add_copy_spec_limit(
os.path.join(self.sa_path, "sa[0-3][0-9]" + suffix),
sizelimit=self.sa_size, tailit=False
)
self.add_copy_spec_limit(
os.path.join(self.sa_path, "sar[0-3][0-9]" + suffix),
sizelimit=self.sa_size, tailit=False
)
try:
dir_list = os.listdir(self.sa_path)
except:
self._log_warn("sar: could not list %s" % self.sa_path)
return
# find all the sa files that don't have an existing sar file
for fname in dir_list:
if fname.startswith('sar'):
continue
if not fname.startswith('sa'):
continue
if len(fname) != 4:
# We either have an "sa" or "sa?" file, or more likely, a
# compressed data file like, "sa??.xz".
#
# FIXME: We don't have a detector for the kind of compression
# use for this file right now, so skip these kinds of files.
continue
sa_data_path = os.path.join(self.sa_path, fname)
sar_filename = 'sar' + fname[2:]
if sar_filename not in dir_list:
sar_cmd = 'sh -c "sar -A -f %s"' % sa_data_path
self.add_cmd_output(sar_cmd, sar_filename)
sadf_cmd = "sadf -x %s" % sa_data_path
self.add_cmd_output(sadf_cmd, "%s.xml" % fname)
class RedHatSar(Sar, RedHatPlugin):
sa_path = '/var/log/sa'
class DebianSar(Sar, DebianPlugin, UbuntuPlugin):
sa_path = '/var/log/sysstat'
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/logs.py 0000644 0001750 0001750 00000010352 12625313241 021310 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
import os
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Logs(Plugin):
"""System logs"""
plugin_name = "logs"
profiles = ('system', 'hardware', 'storage')
def setup(self):
self.add_copy_spec([
"/etc/syslog.conf",
"/etc/rsyslog.conf",
"/etc/rsyslog.d"
])
self.limit = self.get_option("log_size")
self.add_copy_spec_limit("/var/log/boot.log", sizelimit=self.limit)
self.add_copy_spec_limit("/var/log/cloud-init*", sizelimit=self.limit)
self.add_cmd_output([
"journalctl --all --this-boot --no-pager",
"journalctl --all --this-boot --no-pager -o verbose",
])
if self.get_option('all_logs'):
syslog_conf = self.join_sysroot("/etc/syslog.conf")
logs = self.do_regex_find_all("^\S+\s+(-?\/.*$)\s+", syslog_conf)
if self.is_installed("rsyslog") \
or os.path.exists("/etc/rsyslog.conf"):
rsyslog_conf = self.join_sysroot("/etc/rsyslog.conf")
logs += self.do_regex_find_all("^\S+\s+(-?\/.*$)\s+",
rsyslog_conf)
for i in logs:
if i.startswith("-"):
i = i[1:]
if os.path.isfile(i):
self.add_copy_spec_limit(i, sizelimit=self.limit)
def postproc(self):
self.do_path_regex_sub(
r"/etc/rsyslog*",
r"ActionLibdbiPassword (.*)",
r"ActionLibdbiPassword [********]"
)
self.do_path_regex_sub(
r"/etc/rsyslog*",
r"pwd=.*",
r"pwd=[******]"
)
class RedHatLogs(Logs, RedHatPlugin):
option_list = [
("log_days", "the number of days logs to collect", "", 3)
]
def setup(self):
super(RedHatLogs, self).setup()
messages = "/var/log/messages"
self.add_copy_spec_limit("/var/log/secure*", sizelimit=self.limit)
self.add_copy_spec_limit(messages + "*", sizelimit=self.limit)
# collect three days worth of logs by default if the system is
# configured to use the journal and not /var/log/messages
if not os.path.exists(messages) and self.is_installed("systemd"):
try:
days = int(self.get_option("log_days"))
except:
days = 3
if self.get_option("all_logs"):
since_opt = ""
else:
since_opt = '--since="-%ddays"' % days
self.add_cmd_output('journalctl --all %s' % since_opt)
class DebianLogs(Logs, DebianPlugin, UbuntuPlugin):
def setup(self):
super(DebianLogs, self).setup()
if not self.get_option("all_logs"):
limit = self.get_option("log_size")
self.add_copy_spec_limit("/var/log/syslog", sizelimit=limit)
self.add_copy_spec_limit("/var/log/syslog.1", sizelimit=limit)
self.add_copy_spec_limit("/var/log/kern.log", sizelimit=limit)
self.add_copy_spec_limit("/var/log/kern.log.1", sizelimit=limit)
self.add_copy_spec_limit("/var/log/udev", sizelimit=limit)
self.add_copy_spec_limit("/var/log/dist-upgrade", sizelimit=limit)
self.add_copy_spec_limit("/var/log/installer", sizelimit=limit)
self.add_copy_spec_limit("/var/log/unattended-upgrades",
sizelimit=limit)
self.add_cmd_output('ls -alRh /var/log/')
else:
self.add_copy_spec("/var/log/")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/mrgmessg.py 0000644 0001750 0001750 00000002021 12625313241 022162 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin
class MrgMessg(Plugin, RedHatPlugin):
"""MRG Messaging subsystem
"""
plugin_name = 'mrgmessg'
profiles = ('mrg',)
def setup(self):
self.add_copy_spec([
"/etc/qpidd.conf",
"/etc/sasl2/qpidd.conf",
"/var/rhm"
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/postgresql.py 0000644 0001750 0001750 00000012014 12625313241 022544 0 ustar caribou caribou # Copyright (C) 2014 Red Hat, Inc., Sandro Bonazzola
# Copyright (C) 2013 Chris J Arges
# Copyright (C) 2012-2013 Red Hat, Inc., Bryn M. Reeves
# Copyright (C) 2011 Red Hat, Inc., Jesse Jaggars
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
import os
import tempfile
from sos.plugins import Plugin, RedHatPlugin, UbuntuPlugin, DebianPlugin
from sos.utilities import find
class PostgreSQL(Plugin):
"""PostgreSQL RDBMS"""
plugin_name = "postgresql"
profiles = ('services',)
packages = ('postgresql',)
tmp_dir = None
password_warn_text = " (password visible in process listings)"
option_list = [
('pghome', 'PostgreSQL server home directory.', '', '/var/lib/pgsql'),
('username', 'username for pg_dump', '', 'postgres'),
('password', 'password for pg_dump' + password_warn_text, '', False),
('dbname', 'database name to dump for pg_dump', '', ''),
('dbhost', 'database hostname/IP (do not use unix socket)', '', ''),
('dbport', 'database server port number', '', '5432')
]
def pg_dump(self):
dest_file = os.path.join(self.tmp_dir, "sos_pgdump.tar")
# We're only modifying this for ourself and our children so there
# is no need to save and restore environment variables if the user
# decided to pass the password on the command line.
if self.get_option("password") is not False:
os.environ["PGPASSWORD"] = str(self.get_option("password"))
if self.get_option("dbhost"):
cmd = "pg_dump -U %s -h %s -p %s -w -f %s -F t %s" % (
self.get_option("username"),
self.get_option("dbhost"),
self.get_option("dbport"),
dest_file,
self.get_option("dbname")
)
else:
cmd = "pg_dump -C -U %s -w -f %s -F t %s " % (
self.get_option("username"),
dest_file,
self.get_option("dbname")
)
result = self.call_ext_prog(cmd)
if (result['status'] == 0):
self.add_copy_spec(dest_file)
else:
self._log_error(
"Unable to execute pg_dump. Error(%s)" % (result['output'])
)
self.add_alert(
"ERROR: Unable to execute pg_dump. Error(%s)" %
(result['output'])
)
def setup(self):
if self.get_option("dbname"):
if self.get_option("password") or "PGPASSWORD" in os.environ:
self.tmp_dir = tempfile.mkdtemp()
self.pg_dump()
else:
self.soslog.warning(
"password must be supplied to dump a database."
)
self.add_alert(
"WARN: password must be supplied to dump a database."
)
def postproc(self):
import shutil
if self.tmp_dir:
try:
shutil.rmtree(self.tmp_dir)
except shutil.Error:
self.soslog.exception(
"Unable to remove %s." % (self.tmp_dir)
)
self.add_alert("ERROR: Unable to remove %s." % (self.tmp_dir))
class RedHatPostgreSQL(PostgreSQL, RedHatPlugin):
def setup(self):
super(RedHatPostgreSQL, self).setup()
# Copy PostgreSQL log files.
for filename in find("*.log", self.get_option("pghome")):
self.add_copy_spec(filename)
# Copy PostgreSQL config files.
for filename in find("*.conf", self.get_option("pghome")):
self.add_copy_spec(filename)
self.add_copy_spec(
os.path.join(
self.get_option("pghome"),
"data",
"PG_VERSION"
)
)
self.add_copy_spec(
os.path.join(
self.get_option("pghome"),
"data",
"postmaster.opts"
)
)
class DebianPostgreSQL(PostgreSQL, DebianPlugin, UbuntuPlugin):
def setup(self):
super(DebianPostgreSQL, self).setup()
self.add_copy_spec([
"/var/log/postgresql/*.log",
"/etc/postgresql/*/main/*.conf",
"/var/lib/postgresql/*/main/PG_VERSION",
"/var/lib/postgresql/*/main/postmaster.opts"
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/kernel.py 0000644 0001750 0001750 00000006036 12625313247 021636 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
import os
import glob
class Kernel(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
"""Linux kernel
"""
plugin_name = 'kernel'
profiles = ('system', 'hardware', 'kernel')
sys_module = '/sys/module'
def setup(self):
# compat
self.add_cmd_output("uname -a", root_symlink="uname")
self.add_cmd_output("lsmod", root_symlink="lsmod")
self.add_cmd_output("ls -lt /sys/kernel/slab")
try:
modules = os.listdir(self.sys_module)
self.add_cmd_output("modinfo " + " ".join(modules))
except OSError:
self._log_warn("could not list %s" % self.sys_module)
# find /lib/modules/*/{extras,updates,weak-updates} -ls
extra_mod_patterns = [
"/lib/modules/*/extra",
"/lib/modules/*/updates",
"/lib/modules/*/weak-updates",
]
extra_mod_paths = []
for pattern in extra_mod_patterns:
extra_mod_paths.extend(glob.glob(pattern))
self.add_cmd_output([
"dmesg",
"sysctl -a",
"dkms status",
"find %s -ls" % " ".join(extra_mod_paths)
])
clocksource_path = "/sys/devices/system/clocksource/clocksource0/"
self.add_copy_spec([
"/proc/modules",
"/proc/sys/kernel/random/boot_id",
"/sys/module/*/parameters",
"/sys/module/*/initstate",
"/sys/module/*/refcnt",
"/sys/module/*/taint",
"/sys/firmware/acpi/*",
"/proc/kallsyms",
"/proc/buddyinfo",
"/proc/slabinfo",
"/proc/zoneinfo",
"/lib/modules/%s/modules.dep" % self.policy().kernel_version(),
"/etc/conf.modules",
"/etc/modules.conf",
"/etc/modprobe.conf",
"/etc/modprobe.d",
"/etc/sysctl.conf",
"/etc/sysctl.d",
"/lib/sysctl.d",
"/proc/cmdline",
"/proc/driver",
"/proc/sys/kernel/tainted",
"/proc/softirqs",
"/proc/timer*",
"/proc/lock*",
"/proc/misc",
"/var/log/dmesg",
clocksource_path + "available_clocksource",
clocksource_path + "current_clocksource"
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/devices.py 0000644 0001750 0001750 00000002017 12625313241 021765 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Devices(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
""" devices specific commands
"""
plugin_name = 'devices'
profiles = ('system', 'hardware', 'boot')
def setup(self):
self.add_cmd_output("udevadm info --export-db")
# vim: et ts=4 sw=4
sosreport-3.2+git276-g7da50d6/sos/plugins/process.py 0000644 0001750 0001750 00000003176 12625313241 022030 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Process(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
"""process information
"""
plugin_name = 'process'
profiles = ('system',)
def setup(self):
ps_axo = "ps axo"
# process group and thread options
ps_group_opts = "pid,ppid,user,group,lwp,nlwp,start_time,comm,cgroup"
ps_sched_opts = "flags,state,uid,pid,ppid,pgid,sid,cls,pri,addr,sz,"
ps_sched_opts += "wchan,stime,tty,time,cmd"
self.add_copy_spec("/proc/sched_debug")
self.add_cmd_output("ps auxwww", root_symlink="ps")
self.add_cmd_output("pstree", root_symlink="pstree")
self.add_cmd_output("lsof -b +M -n -l", root_symlink="lsof")
self.add_cmd_output([
"ps auxwwwm",
"ps alxwww",
"%s %s" % (ps_axo, ps_group_opts),
"%s %s" % (ps_axo, ps_sched_opts)
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/grub2.py 0000644 0001750 0001750 00000004305 12625313241 021366 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Grub2(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
"""GRUB2 bootloader
"""
plugin_name = 'grub2'
profiles = ('boot',)
packages = ('grub2',)
def setup(self):
self.add_copy_spec([
"/boot/efi/EFI/*/grub.cfg",
"/boot/grub2/grub.cfg",
"/boot/grub2/grubenv",
"/boot/grub/grub.cfg",
"/etc/default/grub",
"/etc/grub2.cfg",
"/etc/grub.d"
])
self.add_cmd_output([
"ls -lanR /boot",
"grub2-mkconfig"
])
def postproc(self):
# the trailing space is required; python treats '_' as whitespace
# causing the passwd_exp to match pbkdf2 passwords and mangle them.
passwd_exp = r"(password )\s*(\S*)\s*(\S*)"
passwd_pbkdf2_exp = r"(password_pbkdf2)\s*(\S*)\s*(\S*)"
passwd_sub = r"\1 \2 ********"
passwd_pbkdf2_sub = r"\1 \2 grub.pbkdf2.********"
self.do_cmd_output_sub(
"grub2-mkconfig",
passwd_pbkdf2_exp,
passwd_pbkdf2_sub
)
self.do_cmd_output_sub(
"grub2-mkconfig",
passwd_exp,
passwd_sub
)
self.do_path_regex_sub(
r".*\/grub\.",
passwd_exp,
passwd_sub
)
self.do_path_regex_sub(
r".*\/grub\.",
passwd_pbkdf2_exp,
passwd_pbkdf2_sub
)
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/cgroups.py 0000644 0001750 0001750 00000002634 12625313241 022032 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Cgroups(Plugin, DebianPlugin, UbuntuPlugin):
"""Control groups subsystem
"""
plugin_name = "cgroups"
profiles = ('system',)
files = ('/proc/cgroups',)
def setup(self):
self.add_copy_spec([
"/proc/cgroups",
"/sys/fs/cgroup"
])
return
class RedHatCgroups(Cgroups, RedHatPlugin):
def setup(self):
super(RedHatCgroups, self).setup()
self.add_copy_spec([
"/etc/sysconfig/cgconfig",
"/etc/sysconfig/cgred",
"/etc/cgsnapshot_blacklist.conf",
"/etc/cgconfig.conf",
"/etc/cgrules.conf"
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/usb.py 0000644 0001750 0001750 00000002116 12625313241 021134 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, UbuntuPlugin, DebianPlugin
class Usb(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
"""USB devices
"""
plugin_name = "usb"
profiles = ('hardware',)
def setup(self):
self.add_copy_spec("/sys/bus/usb")
self.add_cmd_output([
"lsusb",
"lsusb -v",
"lsusb -t"
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/ctdb.py 0000644 0001750 0001750 00000003160 12625313241 021257 0 ustar caribou caribou # Copyright (C) 2014 Red Hat, Inc., Bryn M. Reeves
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Ctdb(Plugin, DebianPlugin, UbuntuPlugin):
"""Samba Clustered TDB
"""
packages = ('ctdb',)
profiles = ('cluster', 'storage')
plugin_name = "ctdb"
def setup(self):
self.add_copy_spec([
"/etc/ctdb/public_addresses",
"/etc/ctdb/static-routes",
"/etc/ctdb/multipathd",
"/var/log/log.ctdb"
])
self.add_cmd_output([
"ctdb ip",
"ctdb ping",
"ctdb status",
"ctdb ifaces",
"ctdb listnodes",
"ctdb listvars",
"ctdb statistics",
"ctdb getdbmap"
])
class RedHatCtdb(Ctdb, RedHatPlugin):
def setup(self):
super(RedHatCtdb, self).setup()
self.add_copy_spec("/etc/sysconfig/ctdb")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/upstart.py 0000644 0001750 0001750 00000003345 12625313241 022052 0 ustar caribou caribou # Copyright (C) 2012 Red Hat, Inc., Bryn M. Reeves
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Upstart(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
"""Upstart init system
"""
plugin_name = 'upstart'
profiles = ('system', 'services', 'boot')
packages = ('upstart',)
def setup(self):
self.add_cmd_output([
'initctl --system list',
'initctl --system version',
'init --version',
"ls -l /etc/init/"
])
# Job Configuration Files
self.add_copy_spec([
'/etc/init.conf',
'/etc/event.d/*',
'/etc/init/*.conf'
])
# State file
self.add_copy_spec('/var/log/upstart/upstart.state')
# Log files
self.add_copy_spec_limit('/var/log/upstart/*',
sizelimit=self.get_option('log_size'))
# Session Jobs (running Upstart as a Session Init)
self.add_copy_spec('/usr/share/upstart/')
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/udev.py 0000644 0001750 0001750 00000002151 12625313241 021305 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Udev(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
"""udev dynamic device management
"""
plugin_name = 'udev'
profiles = ('system', 'hardware', 'boot')
def setup(self):
self.add_copy_spec([
"/etc/udev/udev.conf",
"/lib/udev/rules.d",
"/etc/udev/rules.d/*"
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/libvirt.py 0000644 0001750 0001750 00000005370 12625313241 022023 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, UbuntuPlugin, DebianPlugin
import glob
import os
class Libvirt(Plugin, RedHatPlugin, UbuntuPlugin, DebianPlugin):
"""libvirt virtualization API
"""
plugin_name = 'libvirt'
profiles = ('system', 'virt')
def setup(self):
libvirt_keytab = "/etc/libvirt/krb5.tab"
# authentication databases used for libvirt SASL authentication
self.add_forbidden_path("/etc/libvirt/passwd.db")
self.add_forbidden_path("/etc/libvirt/krb5.tab")
self.add_copy_spec([
"/etc/libvirt/libvirt.conf",
"/etc/libvirt/libvirtd.conf",
"/etc/libvirt/lxc.conf",
"/etc/libvirt/nwfilter/*.xml",
"/etc/libvirt/qemu/*.xml",
"/var/run/libvirt/qemu/*.xml",
"/etc/libvirt/qemu/networks/*.xml",
"/etc/libvirt/qemu/networks/autostart/*.xml",
"/etc/libvirt/storage/*.xml",
"/etc/libvirt/storage/autostart/*.xml",
"/etc/libvirt/qemu-lockd.conf",
"/etc/libvirt/virtlockd.conf"
])
if not self.get_option("all_logs"):
self.add_copy_spec_limit("/var/log/libvirt/libvirtd.log",
sizelimit=5)
self.add_copy_spec_limit("/var/log/libvirt/qemu/*.log",
sizelimit=5)
self.add_copy_spec_limit("/var/log/libvirt/lxc/*.log", sizelimit=5)
self.add_copy_spec_limit("/var/log/libvirt/uml/*.log", sizelimit=5)
else:
self.add_copy_spec("/var/log/libvirt")
if os.path.exists(self.join_sysroot(libvirt_keytab)):
self.add_cmd_output("klist -ket %s" % libvirt_keytab)
self.add_cmd_output("ls -lR /var/lib/libvirt/qemu")
def postproc(self):
for loc in ["/etc/", "/var/run/"]:
for xmlfile in glob.glob(loc + "libvirt/qemu/*.xml"):
self.do_file_sub(
xmlfile,
r"(\s*passwd=\s*')([^']*)('.*)",
r"\1******\3"
)
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/distupgrade.py 0000644 0001750 0001750 00000003270 12625313241 022660 0 ustar caribou caribou # Copyright (C) 2014 Red Hat, Inc., Bryn M. Reeves
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin
class DistUpgrade(Plugin):
""" Distribution upgrade data """
plugin_name = "distupgrade"
profiles = ('system', 'sysmgmt')
files = None
class RedHatDistUpgrade(DistUpgrade, RedHatPlugin):
files = (
"/var/log/upgrade.log",
"/var/log/redhat_update_tool.log",
"/root/preupgrade/all-xccdf*",
"/root/preupgrade/kickstart"
)
def postproc(self):
self.do_file_sub(
"/root/preupgrade/kickstart/anaconda-ks.cfg",
r"(useradd --password) (.*)",
r"\1 ********"
)
self.do_file_sub(
"/root/preupgrade/kickstart/anaconda-ks.cfg",
r"(\s*rootpw\s*).*",
r"\1********"
)
self.do_file_sub(
"/root/preupgrade/kickstart/untrackeduser",
r"\/home\/.*",
r"/home/******** path redacted ********"
)
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/haproxy.py 0000644 0001750 0001750 00000002275 12625313241 022043 0 ustar caribou caribou # Copyright (C) 2014 Red Hat, Inc. Bryn M. Reeves
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin
class HAProxy(Plugin, RedHatPlugin, DebianPlugin):
"""HAProxy load balancer
"""
plugin_name = 'haproxy'
profiles = ('webserver',)
packages = ('haproxy',)
def setup(self):
self.add_copy_spec("/etc/haproxy/haproxy.cfg")
self.add_cmd_output("haproxy -f /etc/haproxy/haproxy.cfg -c")
self.add_copy_spec("/var/log/haproxy.log")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/Makefile 0000644 0001750 0001750 00000001104 12433366740 021436 0 ustar caribou caribou PYTHON=python
PACKAGE = $(shell basename `pwd`)
PYFILES = $(wildcard *.py)
PYVER := $(shell $(PYTHON) -c 'import sys; print("%.3s" %(sys.version))')
PYSYSDIR := $(shell $(PYTHON) -c 'import sys; print(sys.prefix)')
PYLIBDIR = $(PYSYSDIR)/lib/python$(PYVER)
PKGDIR = $(PYLIBDIR)/site-packages/sos/$(PACKAGE)
all:
echo "nada"
clean:
rm -f *.pyc *.pyo *~
install:
mkdir -p $(DESTDIR)/$(PKGDIR)
for p in $(PYFILES) ; do \
install -m 644 $$p $(DESTDIR)/$(PKGDIR)/$$p; \
done
$(PYTHON) -c "import compileall; compileall.compile_dir('$(DESTDIR)/$(PKGDIR)', 1, '$(PYDIR)', 1)"
sosreport-3.2+git276-g7da50d6/sos/plugins/openshift.py 0000644 0001750 0001750 00000014334 12625313241 022347 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin
import os.path
class Openshift(Plugin, RedHatPlugin):
'''Openshift node and broker'''
plugin_name = "openshift"
profiles = ('virt', 'openshift')
# The 'broker' and 'node' options are obsolete but are maintained
# here for compatibility with external programs that call sosreport
# with these names.
option_list = [("broker", "Gathers broker specific files", "slow", False),
("node", "Gathers node specific files", "slow", False)]
ruby = "ruby193"
vendor = "rh"
mco_config_dir = "/opt/%s/%s/root/etc/mcollective" % (vendor, ruby)
gear_base_dir = "/var/lib/openshift"
node_settings_dir = os.path.join(gear_base_dir, ".settings")
node_proxy_dir = os.path.join(gear_base_dir, ".httpd.d")
httpd_config_dir = "/etc/httpd/conf.d"
def is_broker(self):
return os.path.exists("/etc/openshift/broker.conf")
def is_node(self):
return os.path.exists("/etc/openshift/node.conf")
def setup(self):
self.add_copy_spec([
"/etc/openshift-enterprise-release",
"/var/log/openshift",
"/etc/openshift/*.conf",
"/etc/openshift/upgrade",
])
self.add_cmd_output("oo-diagnostics -v")
if self.is_broker():
self.add_copy_spec([
"/etc/openshift/quickstarts.json",
"/etc/openshift/plugins.d/*.conf",
os.path.join(self.mco_config_dir, "client.cfg"),
"/var/www/openshift/broker/httpd/httpd.conf",
"/var/www/openshift/broker/httpd/conf.d/*.conf",
"/var/www/openshift/console/httpd/httpd.conf",
"/var/www/openshift/console/httpd/conf.d/*.conf",
])
self.add_cmd_output([
"oo-accept-broker -v",
"oo-admin-chk -v",
"oo-mco ping",
])
if self.is_node():
self.add_copy_spec([
"/etc/openshift/node-plugins.d/*.conf",
"/etc/openshift/cart.conf.d",
"/etc/openshift/iptables.*.rules",
"/etc/openshift/env",
os.path.join(self.httpd_config_dir,
"openshift-vhost-logconf.include"),
os.path.join(self.httpd_config_dir,
"openshift-http-vhost.include"),
os.path.join(self.httpd_config_dir,
"openshift_restorer.include"),
os.path.join(self.mco_config_dir, "server.cfg"),
os.path.join(self.mco_config_dir, "facts.yaml"),
os.path.join(self.node_settings_dir, "district.info"),
os.path.join(self.node_proxy_dir, "*.conf"),
os.path.join(self.node_proxy_dir, "aliases.txt"),
os.path.join(self.node_proxy_dir, "nodes.txt"),
os.path.join(self.node_proxy_dir, "idler.txt"),
os.path.join(self.node_proxy_dir, "sts.txt"),
os.path.join(self.node_proxy_dir, "routes.json"),
os.path.join(self.node_proxy_dir, "geardb.json"),
os.path.join(self.node_proxy_dir, "sniproxy.json"),
"/var/log/httpd/openshift_log",
"/var/log/mcollective.log",
"/var/log/node-web-proxy/access.log",
"/var/log/node-web-proxy/error.log",
"/var/log/node-web-proxy/websockets.log",
"/var/log/node-web-proxy/supervisor.log",
])
self.add_cmd_output([
"oo-accept-node -v",
"oo-admin-ctl-gears list",
"ls -laZ %s" % self.gear_base_dir,
"ls -la %s" % self.node_proxy_dir
])
def postproc(self):
# Redact broker's MongoDB credentials:
# MONGO_PASSWORD="PasswordForOpenshiftUser"
self.do_file_sub('/etc/openshift/broker.conf',
r"(MONGO_PASSWORD\s*=\s*)(.*)",
r"\1*******")
# Redact session SHA keys:
# SESSION_SECRET=0c31...a7c8
self.do_file_sub('/etc/openshift/broker.conf',
r"(SESSION_SECRET\s*=\s*)(.*)",
r"\1*******")
self.do_file_sub('/etc/openshift/console.conf',
r"(SESSION_SECRET\s*=\s*)(.*)",
r"\1*******")
# Redact passwords of the form:
# plugin.activemq.pool.1.password = Pa$sW0Rd
self.do_file_sub(os.path.join(self.mco_config_dir, "server.cfg"),
r"(.*password\s*=\s*)\S+",
r"\1********")
self.do_file_sub(os.path.join(self.mco_config_dir, "client.cfg"),
r"(.*password\s*=\s*)\S+",
r"\1********")
# Redact DNS plugin credentials
# Dynect DNS: DYNECT_PASSWORD=s0ME-p4$_w0RD._
plugin_dir = '/etc/openshift/plugins.d/'
self.do_file_sub(plugin_dir + 'openshift-origin-dns-dynect.conf',
r"(DYNECT_PASSWORD\s*=\s*)(.*)",
r"\1********")
# Fog cloud: FOG_RACKSPACE_API_KEY="apikey"
self.do_file_sub(plugin_dir + 'openshift-origin-dns-fog.conf',
r"(FOG_RACKSPACE_API_KEY\s*=\s*)(.*)",
r"\1********")
# ISC bind: BIND_KEYVALUE="rndc key"
self.do_file_sub(plugin_dir + 'openshift-origin-dns-nsupdate.conf',
r"(BIND_KEYVALUE\s*=\s*)(.*)",
r"\1********")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/juju.py 0000644 0001750 0001750 00000010254 12625313241 021322 0 ustar caribou caribou # Copyright (C) 2013 Adam Stokes
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
import os
from sos.plugins import Plugin, UbuntuPlugin
from json import loads as json_load
def ensure_service_is_running(service):
def wrapper(callback):
def wrapped_f(self, *args, **kwargs):
try:
result = self.call_ext_prog("service {0} stop".format(service))
if result["status"] != 0:
raise Exception("Cannot stop {0} service".format(service))
callback(self, *args, **kwargs)
except Exception as ex:
self._log_error("Cannot stop {0}, exception: {1}".format(
service,
ex.message))
finally:
self.call_ext_prog("service {0} start".format(service))
return wrapped_f
return wrapper
class Juju(Plugin, UbuntuPlugin):
""" Juju orchestration tool
"""
plugin_name = 'juju'
profiles = ('virt', 'sysmgmt')
packages = ('juju',)
option_list = [
('export-mongodb',
'Export mongodb collections as json files', '', False),
('generate-bundle',
"""Generate a YAML bundle of the current environment
(requires juju-deployerizer)""", '', False),
]
def get_deployed_services(self):
cmd = "juju status --format json"
return json_load(
self.call_ext_prog(cmd)['output'])['services'].keys()
@ensure_service_is_running("juju-db")
def export_mongodb(self):
collections = (
"relations",
"environments",
"linkednetworks",
"system",
"settings",
)
for collection in collections:
self.add_cmd_output(
"/usr/lib/juju/bin/mongoexport --ssl \
--dbpath=/var/lib/juju/db --db juju --collection {0} \
--jsonArray".format(collection),
suggest_filename="{}.json".format(collection))
def setup(self):
self.add_copy_spec([
"/var/lib/juju"
])
limit = self.get_option("log_size")
self.add_copy_spec_limit("/var/log/upstart/juju-db.log",
sizelimit=limit)
self.add_copy_spec_limit("/var/log/upstart/juju-db.log.1",
sizelimit=limit)
if not self.get_option("all_logs"):
# Capture the last bit of all files
for filename in os.listdir("/var/log/juju/"):
if filename.endswith(".log"):
fullname = "/var/log/juju/" + filename
self.add_copy_spec_limit(fullname, sizelimit=limit)
# Do just the all-machines from juju local
self.add_copy_spec_limit("/var/log/juju-*/all-machines.log",
sizelimit=limit)
self.add_cmd_output('ls -alRh /var/log/juju*')
else:
self.add_copy_spec([
"/var/log/juju",
"/var/log/juju-*"
])
self.add_cmd_output([
"juju -v status",
"juju -v get-constraints"
])
for service in self.get_deployed_services():
self.add_cmd_output("juju get {}".format(service))
if self.get_option("export-mongodb"):
self.export_mongodb()
if self.get_option("generate-bundle"):
self.add_cmd_output("juju deployerizer --include-charm-versions",
suggest_filename="juju-env-bundle.yaml")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/ssh.py 0000644 0001750 0001750 00000002205 12625313241 021137 0 ustar caribou caribou # Copyright (C) 2007 Red Hat, Inc., Eugene Teo
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Ssh(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
"""Secure shell service
"""
plugin_name = 'ssh'
profiles = ('services', 'security', 'identity')
def setup(self):
self.add_copy_spec([
"/etc/ssh/ssh_config",
"/etc/ssh/sshd_config"
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/scsi.py 0000644 0001750 0001750 00000002451 12625313241 021306 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, UbuntuPlugin, DebianPlugin
class Scsi(Plugin, RedHatPlugin, UbuntuPlugin, DebianPlugin):
"""SCSI devices
"""
plugin_name = 'scsi'
profiles = ('storage', 'hardware')
def setup(self):
self.add_copy_spec([
"/proc/scsi",
"/etc/stinit.def",
"/sys/bus/scsi",
"/sys/class/scsi_host",
"/sys/class/scsi_disk",
"/sys/class/scsi_device",
"/sys/class/scsi_generic"
])
self.add_cmd_output([
"lsscsi",
"sg_map"
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/lilo.py 0000644 0001750 0001750 00000002021 12625313241 021275 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, UbuntuPlugin
class Lilo(Plugin, RedHatPlugin, UbuntuPlugin):
"""Lilo bootloader
"""
plugin_name = 'lilo'
profiles = ('system', 'boot')
packages = ('lilo',)
def setup(self):
self.add_copy_spec("/etc/lilo.conf")
self.add_cmd_output("lilo -q")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/python.py 0000644 0001750 0001750 00000002164 12625313241 021667 0 ustar caribou caribou # Copyright (C) 2014 Red Hat, Inc.,Poornima M. Kshirsagar
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Python(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
"""Python runtime
"""
plugin_name = 'python'
profiles = ('system',)
packages = ('python',)
def setup(self):
self.add_cmd_output("python -V", suggest_filename="python-version")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/qpid.py 0000644 0001750 0001750 00000007215 12625313247 021313 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin
class Qpid(Plugin, RedHatPlugin):
"""Qpid messaging
"""
plugin_name = 'qpid'
profiles = ('services',)
packages = ('qpidd', 'qpid-cpp-server', 'qpid-tools')
option_list = [("port", "listening port to connect to", '', ""),
("ssl-certificate",
"Path to file containing client SSL certificate", '', ""),
("ssl-key",
"Path to file containing client SSL private key", '', ""),
("ssl", "enforce SSL / amqps connection", '', False)]
def setup(self):
""" performs data collection for qpid broker """
options = ""
amqps_prefix = "" # set amqps:// when SSL is used
if self.get_option("ssl"):
amqps_prefix = "amqps://"
# for either present option, add --option=value to 'options' variable
for option in ["ssl-certificate", "ssl-key"]:
if self.get_option(option):
amqps_prefix = "amqps://"
options = (options + " --%s=" % (option) +
self.get_option(option))
if self.get_option("port"):
options = (options + " -b " + amqps_prefix +
"localhost:%s" % (self.get_option("port")))
self.add_cmd_output([
"qpid-stat -g" + options, # applies since 0.18 version
"qpid-stat -b" + options, # applies to pre-0.18 versions
"qpid-stat -c" + options,
"qpid-stat -e" + options,
"qpid-stat -q" + options,
"qpid-stat -u" + options,
"qpid-stat -m" + options, # applies since 0.18 version
"qpid-config exchanges" + options,
"qpid-config queues" + options,
"qpid-config exchanges -b" + options, # applies to pre-0.18 vers.
"qpid-config queues -b" + options, # applies to pre-0.18 versions
"qpid-config exchanges -r" + options, # applies since 0.18 version
"qpid-config queues -r" + options, # applies since 0.18 version
"qpid-route link list" + options,
"qpid-route route list" + options,
"qpid-cluster" + options, # applies to pre-0.22 versions
"qpid-ha query" + options, # applies since 0.22 version
"ls -lanR /var/lib/qpidd"
])
self.add_copy_spec([
"/etc/qpidd.conf", # applies to pre-0.22 versions
"/etc/qpid/qpidd.conf", # applies since 0.22 version
"/var/lib/qpid/syslog",
"/etc/ais/openais.conf",
"/var/log/cumin.log",
"/var/log/mint.log",
"/etc/sasl2/qpidd.conf",
"/etc/qpid/qpidc.conf",
"/etc/sesame/sesame.conf",
"/etc/cumin/cumin.conf",
"/etc/corosync/corosync.conf",
"/var/lib/sesame",
"/var/log/qpidd.log",
"/var/log/sesame",
"/var/log/cumin"
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/apparmor.py 0000644 0001750 0001750 00000002607 12625313241 022171 0 ustar caribou caribou # Copyright (c) 2012 Adam Stokes
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, UbuntuPlugin
class Apparmor(Plugin, UbuntuPlugin):
"""Apparmor mandatory access control
"""
plugin_name = 'apparmor'
profiles = ('security',)
def setup(self):
self.add_copy_spec([
"/etc/apparmor*"
])
self.add_forbidden_path("/etc/apparmor.d/cache")
self.add_forbidden_path("/etc/apparmor.d/libvirt/libvirt*")
self.add_forbidden_path("/etc/apparmor.d/abstractions")
self.add_cmd_output([
"apparmor_status",
"ls -alh /etc/apparmor.d/abstractions",
"ls -alh /etc/apparmor.d/libvirt",
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/postfix.py 0000644 0001750 0001750 00000003011 12625313241 022032 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Postfix(Plugin):
"""Postfix smtp server
"""
plugin_name = "postfix"
profiles = ('mail', 'services')
packages = ('postfix',)
def setup(self):
self.add_copy_spec([
"/etc/postfix/main.cf",
"/etc/postfix/master.cf"
])
self.add_cmd_output("postconf")
class RedHatPostfix(Postfix, RedHatPlugin):
files = ('/etc/rc.d/init.d/postfix',)
packages = ('postfix',)
def setup(self):
super(RedHatPostfix, self).setup()
self.add_copy_spec("/etc/mail")
class DebianPostfix(Postfix, DebianPlugin, UbuntuPlugin):
packages = ('postfix',)
def setup(self):
super(DebianPostfix, self).setup()
self.add_copy_spec("/etc/postfix/dynamicmaps.cf")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/ovirt_hosted_engine.py 0000644 0001750 0001750 00000006012 12435106707 024406 0 ustar caribou caribou # Copyright (C) 2014 Red Hat, Inc., Sandro Bonazzola
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
import glob
from sos.plugins import Plugin, RedHatPlugin
class OvirtHostedEngine(Plugin, RedHatPlugin):
"""oVirt Hosted Engine"""
packages = (
'ovirt-hosted-engine-setup',
'ovirt-hosted-engine-ha',
)
plugin_name = 'ovirt_hosted_engine'
profiles = ('virt',)
SETUP_LOG_GLOB = '/var/log/ovirt-hosted-engine-setup/*.log'
HA_LOG_GLOB = '/var/log/ovirt-hosted-engine-ha/*.log'
def setup(self):
self.limit = self.get_option('log_size')
# Add configuration files
# Collecting the whole directory since it may contain branding
# configuration files or third party plugins configuration files
self.add_copy_spec(['/etc/ovirt-hosted-engine-setup.env.d/'])
self.add_copy_spec([
'/etc/ovirt-hosted-engine/answers.conf',
'/etc/ovirt-hosted-engine/hosted-engine.conf',
'/etc/ovirt-hosted-engine/vm.conf',
'/etc/ovirt-hosted-engine-ha/agent.conf',
'/etc/ovirt-hosted-engine-ha/agent-log.conf',
'/etc/ovirt-hosted-engine-ha/broker.conf',
'/etc/ovirt-hosted-engine-ha/broker-log.conf',
'/etc/ovirt-hosted-engine-ha/notifications/state_transition.txt',
])
all_setup_logs = glob.glob(self.SETUP_LOG_GLOB)
all_setup_logs.sort(reverse=True)
if len(all_setup_logs):
# Add latest ovirt-hosted-engine-setup log file
self.add_copy_spec(all_setup_logs[0])
# Add older ovirt-hosted-engine-setup log files only if requested
if self.get_option('all_logs'):
self.add_copy_spec_limit(
self.SETUP_LOG_GLOB,
sizelimit=self.limit
)
self.add_copy_spec([
'/var/log/ovirt-hosted-engine-ha/agent.log',
'/var/log/ovirt-hosted-engine-ha/broker.log',
])
# Add older ovirt-hosted-engine-ha log files only if requested
if self.get_option('all_logs'):
self.add_copy_spec_limit(
self.HA_LOG_GLOB,
sizelimit=self.limit,
)
# Add run-time status
self.add_cmd_output([
'hosted-engine --vm-status',
'hosted-engine --check-liveliness',
])
# vim: expandtab tabstop=4 shiftwidth=4
sosreport-3.2+git276-g7da50d6/sos/plugins/pxe.py 0000644 0001750 0001750 00000003257 12625313241 021146 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Pxe(Plugin):
"""PXE service
"""
plugin_name = "pxe"
profiles = ('sysmgmt', 'network')
option_list = [("tftpboot", 'gathers content from the tftpboot path',
'slow', False)]
class RedHatPxe(Pxe, RedHatPlugin):
files = ('/usr/sbin/pxeos',)
packages = ('system-config-netboot-cmd',)
def setup(self):
super(RedHatPxe, self).setup()
self.add_cmd_output("/usr/sbin/pxeos -l")
self.add_copy_spec("/etc/dhcpd.conf")
if self.get_option("tftpboot"):
self.add_copy_spec("/tftpboot")
class DebianPxe(Pxe, DebianPlugin, UbuntuPlugin):
packages = ('tftpd-hpa',)
def setup(self):
super(DebianPxe, self).setup()
self.add_copy_spec([
"/etc/dhcp/dhcpd.conf",
"/etc/default/tftpd-hpa"
])
if self.get_option("tftpboot"):
self.add_copy_spec("/var/lib/tftpboot")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/__init__.py 0000644 0001750 0001750 00000100226 12625313241 022103 0 ustar caribou caribou # Copyright (C) 2006 Steve Conklin
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
""" This exports methods available for use by plugins for sos """
from __future__ import with_statement
from sos.utilities import (sos_get_command_output, import_module, grep,
fileobj, tail)
import os
import glob
import re
import stat
from time import time
import logging
import fnmatch
import errno
# PYCOMPAT
import six
from six.moves import zip, filter
def regex_findall(regex, fname):
'''Return a list of all non overlapping matches in the string(s)'''
try:
with fileobj(fname) as f:
return re.findall(regex, f.read(), re.MULTILINE)
except AttributeError:
return []
def _mangle_command(command, name_max):
mangledname = re.sub(r"^/(usr/|)(bin|sbin)/", "", command)
mangledname = re.sub(r"[^\w\-\.\/]+", "_", mangledname)
mangledname = re.sub(r"/", ".", mangledname).strip(" ._-")
mangledname = mangledname[0:name_max]
return mangledname
def _path_in_path_list(path, path_list):
return any(p in path for p in path_list)
def _node_type(st):
""" return a string indicating the type of special node represented by
the stat buffer st (block, character, fifo, socket).
"""
_types = [
(stat.S_ISBLK, "block device"),
(stat.S_ISCHR, "character device"),
(stat.S_ISFIFO, "named pipe"),
(stat.S_ISSOCK, "socket")
]
for t in _types:
if t[0](st.st_mode):
return t[1]
class Plugin(object):
""" This is the base class for sosreport plugins. Plugins should subclass
this and set the class variables where applicable.
plugin_name is a string returned by plugin.name(). If this is set to None
(the default) class_.__name__.tolower() will be returned. Be sure to set
this if you are defining multiple plugins that do the same thing on
different platforms.
requires_root is a boolean that specifies whether or not sosreport should
execute this plugin as a super user.
version is a string representing the version of the plugin. This can be
useful for post-collection tooling.
packages (files) is an iterable of the names of packages (the paths
of files) to check for before running this plugin. If any of these packages
or files is found on the system, the default implementation of
check_enabled will return True.
profiles is an iterable of profile names that this plugin belongs to.
Whenever any of the profiles is selected on the command line the plugin
will be enabled (subject to normal check_enabled tests).
"""
plugin_name = None
requires_root = True
version = 'unversioned'
packages = ()
files = ()
archive = None
profiles = ()
sysroot = '/'
def __init__(self, commons):
if not getattr(self, "option_list", False):
self.option_list = []
self.copied_files = []
self.executed_commands = []
self.alerts = []
self.custom_text = ""
self.opt_names = []
self.opt_parms = []
self.commons = commons
self.forbidden_paths = []
self.copy_paths = set()
self.copy_strings = []
self.collect_cmds = []
self.sysroot = commons['sysroot']
self.soslog = self.commons['soslog'] if 'soslog' in self.commons \
else logging.getLogger('sos')
# get the option list into a dictionary
for opt in self.option_list:
self.opt_names.append(opt[0])
self.opt_parms.append({'desc': opt[1], 'speed': opt[2],
'enabled': opt[3]})
@classmethod
def name(class_):
"""Returns the plugin's name as a string. This should return a
lowercase string.
"""
if class_.plugin_name:
return class_.plugin_name
return class_.__name__.lower()
def _format_msg(self, msg):
return "[plugin:%s] %s" % (self.name(), msg)
def _log_error(self, msg):
self.soslog.error(self._format_msg(msg))
def _log_warn(self, msg):
self.soslog.warning(self._format_msg(msg))
def _log_info(self, msg):
self.soslog.info(self._format_msg(msg))
def _log_debug(self, msg):
self.soslog.debug(self._format_msg(msg))
def policy(self):
return self.commons["policy"]
def join_sysroot(self, path):
if path[0] == os.sep:
path = path[1:]
return os.path.join(self.sysroot, path)
def strip_sysroot(self, path):
if not self.use_sysroot():
return path
if path.startswith(self.sysroot):
return path[len(self.sysroot):]
return path
def use_sysroot(self):
return self.sysroot != os.path.abspath(os.sep)
def tmp_in_sysroot(self):
paths = [self.sysroot, self.archive.get_tmp_dir()]
return os.path.commonprefix(paths) == self.sysroot
def is_installed(self, package_name):
'''Is the package $package_name installed?'''
return self.policy().pkg_by_name(package_name) is not None
def do_cmd_output_sub(self, cmd, regexp, subst):
'''Apply a regexp substitution to command output archived by sosreport.
cmd is the command name from which output is collected (i.e. excluding
parameters). The regexp can be a string or a compiled re object. The
substitution string, subst, is a string that replaces each occurrence
of regexp in each file collected from cmd. Internally 'cmd' is treated
as a glob with a leading and trailing '*' and each matching file from
the current module's command list is subjected to the replacement.
This function returns the number of replacements made.
'''
globstr = '*' + cmd + '*'
self._log_debug("substituting '%s' for '%s' in commands matching '%s'"
% (subst, regexp, globstr))
if not self.executed_commands:
return 0
replacements = None
try:
for called in self.executed_commands:
# was anything collected?
if called['file'] is None:
continue
if fnmatch.fnmatch(called['exe'], globstr):
path = os.path.join(self.commons['cmddir'], called['file'])
self._log_debug("applying substitution to '%s'" % path)
readable = self.archive.open_file(path)
result, replacements = re.subn(
regexp, subst, readable.read())
if replacements:
self.archive.add_string(result, path)
except Exception as e:
msg = "regex substitution failed for '%s' with: '%s'"
self._log_error(msg % (called['exe'], e))
replacements = None
return replacements
def do_file_sub(self, srcpath, regexp, subst):
'''Apply a regexp substitution to a file archived by sosreport.
srcpath is the path in the archive where the file can be found. regexp
can be a regexp string or a compiled re object. subst is a string to
replace each occurance of regexp in the content of srcpath.
This function returns the number of replacements made.
'''
try:
path = self._get_dest_for_srcpath(srcpath)
self._log_debug("substituting scrpath '%s'" % srcpath)
self._log_debug("substituting '%s' for '%s' in '%s'"
% (subst, regexp, path))
if not path:
return 0
readable = self.archive.open_file(path)
result, replacements = re.subn(regexp, subst, readable.read())
if replacements:
self.archive.add_string(result, srcpath)
else:
replacements = 0
except Exception as e:
msg = "regex substitution failed for '%s' with: '%s'"
self._log_error(msg % (path, e))
replacements = 0
return replacements
def do_path_regex_sub(self, pathexp, regexp, subst):
'''Apply a regexp substituation to a set of files archived by
sos. The set of files to be substituted is generated by matching
collected file pathnames against pathexp which may be a regular
expression string or compiled re object. The portion of the file
to be replaced is specified via regexp and the replacement string
is passed in subst.'''
if not hasattr(pathexp, "match"):
pathexp = re.compile(pathexp)
match = pathexp.match
file_list = [f for f in self.copied_files if match(f['srcpath'])]
for file in file_list:
self.do_file_sub(file['srcpath'], regexp, subst)
def do_regex_find_all(self, regex, fname):
return regex_findall(regex, fname)
def _copy_symlink(self, srcpath):
# the target stored in the original symlink
linkdest = os.readlink(srcpath)
dest = os.path.join(os.path.dirname(srcpath), linkdest)
# Absolute path to the link target. If SYSROOT != '/' this path
# is relative to the host root file system.
absdest = os.path.normpath(dest)
# adjust the target used inside the report to always be relative
if os.path.isabs(linkdest):
reldest = os.path.relpath(linkdest, os.path.dirname(srcpath))
# trim leading /sysroot
if self.use_sysroot():
reldest = reldest[len(os.sep + os.pardir):]
self._log_debug("made link target '%s' relative as '%s'"
% (linkdest, reldest))
else:
reldest = linkdest
self._log_debug("copying link '%s' pointing to '%s' with isdir=%s"
% (srcpath, linkdest, os.path.isdir(absdest)))
dstpath = self.strip_sysroot(srcpath)
# use the relative target path in the tarball
self.archive.add_link(reldest, dstpath)
if os.path.isdir(absdest):
self._log_debug("link '%s' is a directory, skipping..." % linkdest)
return
# copy the symlink target translating relative targets
# to absolute paths to pass to _do_copy_path.
self._log_debug("normalized link target '%s' as '%s'"
% (linkdest, absdest))
# skip recursive copying of symlink pointing to itself.
if (absdest != srcpath):
self._do_copy_path(self.strip_sysroot(absdest))
else:
self._log_debug("link '%s' points to itself, skipping target..."
% linkdest)
self.copied_files.append({'srcpath': srcpath,
'dstpath': dstpath,
'symlink': "yes",
'pointsto': linkdest})
def _copy_dir(self, srcpath):
try:
for afile in os.listdir(srcpath):
self._log_debug("recursively adding '%s' from '%s'"
% (afile, srcpath))
self._do_copy_path(os.path.join(srcpath, afile), dest=None)
except OSError as e:
if e.errno == errno.ELOOP:
msg = "Too many levels of symbolic links copying"
self._log_error("_copy_dir: %s '%s'" % (msg, srcpath))
return
raise e
def _get_dest_for_srcpath(self, srcpath):
if self.use_sysroot():
srcpath = self.join_sysroot(srcpath)
for copied in self.copied_files:
if srcpath == copied["srcpath"]:
return copied["dstpath"]
return None
def _is_forbidden_path(self, path):
if self.use_sysroot():
path = self.join_sysroot(path)
return _path_in_path_list(path, self.forbidden_paths)
def _copy_node(self, path, st):
dev_maj = os.major(st.st_rdev)
dev_min = os.minor(st.st_rdev)
mode = st.st_mode
self.archive.add_node(path, mode, os.makedev(dev_maj, dev_min))
# Methods for copying files and shelling out
def _do_copy_path(self, srcpath, dest=None):
'''Copy file or directory to the destination tree. If a directory, then
everything below it is recursively copied. A list of copied files are
saved for use later in preparing a report.
'''
if self._is_forbidden_path(srcpath):
self._log_debug("skipping forbidden path '%s'" % srcpath)
return ''
if not dest:
dest = srcpath
if self.use_sysroot():
dest = self.strip_sysroot(dest)
try:
st = os.lstat(srcpath)
except (OSError, IOError):
self._log_info("failed to stat '%s'" % srcpath)
return
if stat.S_ISLNK(st.st_mode):
self._copy_symlink(srcpath)
return
else:
if stat.S_ISDIR(st.st_mode):
self._copy_dir(srcpath)
return
# handle special nodes (block, char, fifo, socket)
if not (stat.S_ISREG(st.st_mode) or stat.S_ISDIR(st.st_mode)):
ntype = _node_type(st)
self._log_debug("creating %s node at archive:'%s'"
% (ntype, dest))
self._copy_node(srcpath, st)
return
# if we get here, it's definitely a regular file (not a symlink or dir)
self._log_debug("copying path '%s' to archive:'%s'" % (srcpath, dest))
# if not readable(srcpath)
if not st.st_mode & 0o444:
# FIXME: reflect permissions in archive
self.archive.add_string("", dest)
else:
self.archive.add_file(srcpath, dest)
self.copied_files.append({
'srcpath': srcpath,
'dstpath': dest,
'symlink': "no"
})
def add_forbidden_path(self, forbidden):
"""Specify a path to not copy, even if it's part of a copy_specs[]
entry.
"""
if self.use_sysroot():
forbidden = self.join_sysroot(forbidden)
# Glob case handling is such that a valid non-glob is a reduced glob
for path in glob.glob(forbidden):
self.forbidden_paths.append(path)
def get_all_options(self):
"""return a list of all options selected"""
return (self.opt_names, self.opt_parms)
def set_option(self, optionname, value):
'''set the named option to value.'''
for name, parms in zip(self.opt_names, self.opt_parms):
if name == optionname:
parms['enabled'] = value
return True
else:
return False
def get_option(self, optionname, default=0):
"""Returns the first value that matches 'optionname' in parameters
passed in via the command line or set via set_option or via the
global_plugin_options dictionary, in that order.
optionaname may be iterable, in which case the first option that
matches any of the option names is returned.
"""
global_options = ('verify', 'all_logs', 'log_size')
if optionname in global_options:
return getattr(self.commons['cmdlineopts'], optionname)
def _check(key):
if hasattr(optionname, "__iter__"):
return key in optionname
else:
return key == optionname
for name, parms in zip(self.opt_names, self.opt_parms):
if _check(name):
val = parms['enabled']
if val is not None:
return val
items = six.iteritems(self.commons.get('global_plugin_options', {}))
for key, value in items:
if _check(key):
return value
return default
def get_option_as_list(self, optionname, delimiter=",", default=None):
'''Will try to return the option as a list separated by the
delimiter.
'''
option = self.get_option(optionname)
try:
opt_list = [opt.strip() for opt in option.split(delimiter)]
return list(filter(None, opt_list))
except Exception:
return default
def _add_copy_paths(self, copy_paths):
self.copy_paths.update(copy_paths)
def add_copy_spec_limit(self, copyspec, sizelimit=None, tailit=True):
"""Add a file or glob but limit it to sizelimit megabytes. If fname is
a single file the file will be tailed to meet sizelimit. If the first
file in a glob is too large it will be tailed to meet the sizelimit.
"""
if not (copyspec and len(copyspec)):
return False
if self.use_sysroot():
copyspec = self.join_sysroot(copyspec)
files = glob.glob(copyspec)
files.sort()
if len(files) == 0:
return
current_size = 0
limit_reached = False
sizelimit *= 1024 * 1024 # in MB
_file = None
for _file in files:
current_size += os.stat(_file)[stat.ST_SIZE]
if sizelimit and current_size > sizelimit:
limit_reached = True
break
self._add_copy_paths([_file])
if limit_reached and tailit:
file_name = _file
if file_name[0] == os.sep:
file_name = file_name.lstrip(os.sep)
strfile = file_name.replace(os.path.sep, ".") + ".tailed"
self.add_string_as_file(tail(_file, sizelimit), strfile)
rel_path = os.path.relpath('/', os.path.dirname(_file))
link_path = os.path.join(rel_path, 'sos_strings',
self.name(), strfile)
self.archive.add_link(link_path, _file)
def add_copy_spec(self, copyspecs):
"""Add a file specification (can be file, dir,or shell glob) to be
copied into the sosreport by this module.
"""
if isinstance(copyspecs, six.string_types):
copyspecs = [copyspecs]
for copyspec in copyspecs:
if self.use_sysroot():
copyspec = self.join_sysroot(copyspec)
if not (copyspec and len(copyspec)):
self._log_warn("added null or empty copy spec")
return False
copy_paths = self._expand_copy_spec(copyspec)
self._add_copy_paths(copy_paths)
self._log_info("added copyspec '%s'" % copy_paths)
def get_command_output(self, prog, timeout=300, stderr=True,
chroot=True, runat=None):
if chroot or self.commons['cmdlineopts'].chroot == 'always':
root = self.sysroot
else:
root = None
result = sos_get_command_output(prog, timeout=timeout, stderr=stderr,
chroot=root, chdir=runat)
if result['status'] == 124:
self._log_warn("command '%s' timed out after %ds"
% (prog, timeout))
# command not found or not runnable
if result['status'] == 126 or result['status'] == 127:
# automatically retry chroot'ed commands in the host namespace
if chroot and self.commons['cmdlineopts'].chroot != 'always':
self._log_info("command '%s' not found in %s - "
"re-trying in host root"
% (prog.split()[0], root))
return self.get_command_output(prog, timeout=timeout,
chroot=False, runat=runat)
self._log_debug("could not run '%s': command not found" % prog)
return result
def call_ext_prog(self, prog, timeout=300, stderr=True,
chroot=True, runat=None):
"""Execute a command independantly of the output gathering part of
sosreport.
"""
return self.get_command_output(prog, timeout=timeout, stderr=stderr,
chroot=chroot, runat=runat)
def check_ext_prog(self, prog):
"""Execute a command independently of the output gathering part of
sosreport and check the return code. Return True for a return code of 0
and False otherwise.
"""
return self.call_ext_prog(prog)['status'] == 0
def add_cmd_output(self, cmds, suggest_filename=None,
root_symlink=None, timeout=300, stderr=True,
chroot=True, runat=None):
"""Run a program or a list of programs and collect the output"""
if isinstance(cmds, six.string_types):
cmds = [cmds]
if len(cmds) > 1 and (suggest_filename or root_symlink):
self._log_warn("ambiguous filename or symlink for command list")
for cmd in cmds:
cmdt = (
cmd, suggest_filename, root_symlink, timeout, stderr,
chroot, runat
)
_tuplefmt = "('%s', '%s', '%s', %s, '%s', '%s', '%s')"
_logstr = "packed command tuple: " + _tuplefmt
self._log_debug(_logstr % cmdt)
self.collect_cmds.append(cmdt)
self._log_info("added cmd output '%s'" % cmd)
def get_cmd_output_path(self, name=None, make=True):
"""Return a path into which this module should store collected
command output
"""
cmd_output_path = os.path.join(self.archive.get_tmp_dir(),
'sos_commands', self.name())
if name:
cmd_output_path = os.path.join(cmd_output_path, name)
if make:
os.makedirs(cmd_output_path)
return cmd_output_path
def file_grep(self, regexp, *fnames):
"""Returns lines matched in fnames, where fnames can either be
pathnames to files to grep through or open file objects to grep through
line by line.
"""
return grep(regexp, *fnames)
def _mangle_command(self, exe):
name_max = self.archive.name_max()
return _mangle_command(exe, name_max)
def _make_command_filename(self, exe):
"""The internal function to build up a filename based on a command."""
outfn = os.path.join(self.commons['cmddir'], self.name(),
self._mangle_command(exe))
# check for collisions
if os.path.exists(outfn):
inc = 2
while True:
newfn = "%s_%d" % (outfn, inc)
if not os.path.exists(newfn):
outfn = newfn
break
inc += 1
return outfn
def add_string_as_file(self, content, filename):
"""Add a string to the archive as a file named `filename`"""
self.copy_strings.append((content, filename))
content = "..." + (content.splitlines()[0]).decode('utf8', 'ignore')
self._log_debug("added string '%s' as '%s'" % (content, filename))
def get_cmd_output_now(self, exe, suggest_filename=None,
root_symlink=False, timeout=300, stderr=True,
chroot=True, runat=None):
"""Execute a command and save the output to a file for inclusion in the
report.
"""
start = time()
result = self.get_command_output(exe, timeout=timeout, stderr=stderr,
chroot=chroot, runat=runat)
# 126 means 'found but not executable'
if result['status'] == 126 or result['status'] == 127:
return None
self._log_debug("collected output of '%s' in %s"
% (exe.split()[0], time() - start))
if suggest_filename:
outfn = self._make_command_filename(suggest_filename)
else:
outfn = self._make_command_filename(exe)
outfn_strip = outfn[len(self.commons['cmddir'])+1:]
self.archive.add_string(result['output'], outfn)
if root_symlink:
self.archive.add_link(outfn, root_symlink)
# save info for later
# save in our list
self.executed_commands.append({'exe': exe, 'file': outfn_strip})
self.commons['xmlreport'].add_command(cmdline=exe,
exitcode=result['status'],
f_stdout=outfn_strip)
return os.path.join(self.archive.get_archive_path(), outfn)
def is_module_loaded(self, module_name):
"""Return whether specified moudle as module_name is loaded or not"""
if len(grep("^" + module_name + " ", "/proc/modules")) == 0:
return None
else:
return True
# For adding output
def add_alert(self, alertstring):
"""Add an alert to the collection of alerts for this plugin. These
will be displayed in the report
"""
self.alerts.append(alertstring)
def add_custom_text(self, text):
"""Append text to the custom text that is included in the report. This
is freeform and can include html.
"""
self.custom_text += text
def _expand_copy_spec(self, copyspec):
return glob.glob(copyspec)
def _collect_copy_specs(self):
for path in self.copy_paths:
self._log_info("collecting path '%s'" % path)
self._do_copy_path(path)
def _collect_cmd_output(self):
for progs in zip(self.collect_cmds):
(
prog,
suggest_filename, root_symlink,
timeout,
stderr,
chroot, runat
) = progs[0]
self._log_debug("unpacked command tuple: " +
"('%s', '%s', '%s', %s, '%s', '%s', '%s')" %
progs[0])
self._log_info("collecting output of '%s'" % prog)
self.get_cmd_output_now(prog, suggest_filename=suggest_filename,
root_symlink=root_symlink, timeout=timeout,
stderr=stderr, chroot=chroot, runat=runat)
def _collect_strings(self):
for string, file_name in self.copy_strings:
content = "..."
content += (string.splitlines()[0]).decode('utf8', 'ignore')
self._log_info("collecting string '%s' as '%s'"
% (content, file_name))
try:
self.archive.add_string(string,
os.path.join('sos_strings',
self.name(),
file_name))
except Exception as e:
self._log_debug("could not add string '%s': %s"
% (file_name, e))
def collect(self):
"""Collect the data for a plugin."""
start = time()
self._collect_copy_specs()
self._collect_cmd_output()
self._collect_strings()
fields = (self.name(), time() - start)
self._log_debug("collected plugin '%s' in %s" % fields)
def get_description(self):
""" This function will return the description for the plugin"""
try:
if hasattr(self, '__doc__') and self.__doc__:
return self.__doc__.strip()
return super(self.__class__, self).__doc__.strip()
except:
return ""
def check_enabled(self):
"""This method will be used to verify that a plugin should execute
given the condition of the underlying environment. The default
implementation will return True if neither class.files or
class.packages is specified. If either are specified the plugin will
check for the existence of any of the supplied files or packages and
return True if any exist. It is encouraged to override this method if
this behavior isn't applicable.
"""
# some files or packages have been specified for this package
if self.files or self.packages:
if isinstance(self.files, six.string_types):
self.files = [self.files]
if isinstance(self.packages, six.string_types):
self.packages = [self.packages]
return (any(os.path.exists(fname) for fname in self.files) or
any(self.is_installed(pkg) for pkg in self.packages))
return True
def default_enabled(self):
"""This decides whether a plugin should be automatically loaded or
only if manually specified in the command line."""
return True
def setup(self):
"""Collect the list of files declared by the plugin. This method
may be overridden to add further copy_specs, forbidden_paths, and
external programs if required.
"""
self.add_copy_spec(list(self.files))
def postproc(self):
"""Perform any postprocessing. To be replaced by a plugin if required.
"""
pass
def report(self):
""" Present all information that was gathered in an html file that
allows browsing the results.
"""
# make this prettier
html = '
\n' % self.name()
# Intro
html = html + " Plugin " + self.name() + "
\n"
# Files
if len(self.copied_files):
html = html + "Files copied:
\n"
for afile in self.copied_files:
html = html + '- %s' % \
(".." + afile['dstpath'], afile['srcpath'])
if afile['symlink'] == "yes":
html = html + " (symlink to %s)" % afile['pointsto']
html = html + '
\n'
html = html + "
\n"
# Command Output
if len(self.executed_commands):
html = html + "Commands Executed:
\n"
# convert file name to relative path from our root
# don't use relpath - these are HTML paths not OS paths.
for cmd in self.executed_commands:
if cmd["file"] and len(cmd["file"]):
cmd_rel_path = "../" + self.commons['cmddir'] \
+ "/" + cmd['file']
html = html + '- %s
\n' % \
(cmd_rel_path, cmd['exe'])
else:
html = html + '- %s
\n' % (cmd['exe'])
html = html + "
\n"
# Alerts
if len(self.alerts):
html = html + "Alerts:
\n"
for alert in self.alerts:
html = html + '- %s
\n' % alert
html = html + "
\n"
# Custom Text
if self.custom_text != "":
html = html + "Additional Information:
\n"
html = html + self.custom_text + "
\n"
return html
class RedHatPlugin(object):
"""Tagging class for Red Hat's Linux distributions"""
pass
class PowerKVMPlugin(RedHatPlugin):
"""Tagging class for IBM PowerKVM Linux"""
pass
class ZKVMPlugin(RedHatPlugin):
"""Tagging class for IBM ZKVM Linux"""
pass
class UbuntuPlugin(object):
"""Tagging class for Ubuntu Linux"""
pass
class DebianPlugin(object):
"""Tagging class for Debian Linux"""
pass
class IndependentPlugin(object):
"""Tagging class for plugins that can run on any platform"""
pass
class ExperimentalPlugin(object):
"""Tagging class that indicates that this plugin is experimental"""
pass
def import_plugin(name, superclasses=None):
"""Import name as a module and return a list of all classes defined in that
module. superclasses should be a tuple of valid superclasses to import,
this defaults to (Plugin,).
"""
plugin_fqname = "sos.plugins.%s" % name
if not superclasses:
superclasses = (Plugin,)
return import_module(plugin_fqname, superclasses)
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/iscsitarget.py 0000644 0001750 0001750 00000003156 12625313241 022671 0 ustar caribou caribou # Copyright (C) 2007-2012 Red Hat, Inc., Ben Turner
# Copyright (C) 2012 Adam Stokes
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class IscsiTarget(Plugin):
"""iSCSI target
"""
plugin_name = "iscsitarget"
profiles = ('storage',)
class RedHatIscsiTarget(IscsiTarget, RedHatPlugin):
packages = ('scsi-target-utils',)
def setup(self):
super(RedHatIscsiTarget, self).setup()
self.add_copy_spec("/etc/tgt/targets.conf")
self.add_cmd_output("tgtadm --lld iscsi --op show --mode target")
class DebianIscsiTarget(IscsiTarget, DebianPlugin, UbuntuPlugin):
packages = ('iscsitarget',)
def setup(self):
super(DebianIscsiTarget, self).setup()
self.add_copy_spec([
"/etc/iet",
"/etc/sysctl.d/30-iscsitarget.conf",
"/etc/default/iscsitarget"
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/ceph.py 0000644 0001750 0001750 00000003507 12625313241 021267 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, UbuntuPlugin
class Ceph(Plugin, RedHatPlugin, UbuntuPlugin):
"""CEPH distributed storage
"""
plugin_name = 'ceph'
profiles = ('storage', 'virt')
option_list = [
("log", "gathers all ceph logs", "slow", False)
]
packages = (
'ceph',
'ceph-mds',
'ceph-common',
'libcephfs1',
'ceph-fs-common',
'calamari-server',
'librados2'
)
def setup(self):
self.add_copy_spec([
"/etc/ceph/",
"/var/log/ceph/",
"/etc/calamari/",
"/var/log/calamari",
"/var/log/radosgw"
])
self.add_cmd_output([
"ceph status",
"ceph health detail",
"ceph osd tree",
"ceph osd stat",
"ceph osd dump",
"ceph mon stat",
"ceph mon dump",
"ceph df",
"ceph report"
])
self.add_forbidden_path("/etc/ceph/*keyring")
self.add_forbidden_path("/var/lib/ceph/*/*keyring")
self.add_forbidden_path("/var/lib/ceph/*keyring")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/block.py 0000644 0001750 0001750 00000003520 12625313241 021435 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
import os
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Block(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
"""Block device information
"""
plugin_name = 'block'
profiles = ('storage', 'hardware')
def setup(self):
self.add_cmd_output([
"lsblk",
"blkid -c /dev/null",
"blockdev --report",
"ls -lanR /dev",
"ls -lanR /sys/block"
])
# legacy location for non-/run distributions
self.add_copy_spec([
"/etc/blkid.tab",
"/run/blkid/blkid.tab",
"/proc/partitions",
"/proc/diskstats"
])
if os.path.isdir("/sys/block"):
for disk in os.listdir("/sys/block"):
if disk in [".", ".."] or disk.startswith("ram"):
continue
disk_path = os.path.join('/dev/', disk)
self.add_cmd_output([
"udevadm info -ap /sys/block/%s" % (disk),
"parted -s %s unit s print" % (disk_path),
"fdisk -l %s" % disk_path
])
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/apache.py 0000644 0001750 0001750 00000004442 12625313241 021570 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin
class Apache(Plugin):
"""Apache http daemon
"""
plugin_name = "apache"
profiles = ('webserver', 'openshift')
option_list = [
("log", "gathers all apache logs", "slow", False)
]
class RedHatApache(Apache, RedHatPlugin):
files = ('/etc/httpd/conf/httpd.conf',)
def setup(self):
super(RedHatApache, self).setup()
self.add_copy_spec([
"/etc/httpd/conf/httpd.conf",
"/etc/httpd/conf.d/*.conf",
"/etc/httpd/conf.modules.d/*.conf"
])
self.add_forbidden_path("/etc/httpd/conf/password.conf")
# collect only the current log set by default
self.add_copy_spec_limit("/var/log/httpd/access_log", 5)
self.add_copy_spec_limit("/var/log/httpd/error_log", 5)
self.add_copy_spec_limit("/var/log/httpd/ssl_access_log", 5)
self.add_copy_spec_limit("/var/log/httpd/ssl_error_log", 5)
if self.get_option("log"):
self.add_copy_spec("/var/log/httpd/*")
class DebianApache(Apache, DebianPlugin, UbuntuPlugin):
files = ('/etc/apache2/apache2.conf',)
def setup(self):
super(DebianApache, self).setup()
self.add_copy_spec([
"/etc/apache2/*",
"/etc/default/apache2"
])
# collect only the current log set by default
self.add_copy_spec_limit("/var/log/apache2/access_log", 15)
self.add_copy_spec_limit("/var/log/apache2/error_log", 15)
if self.get_option("log"):
self.add_copy_spec("/var/log/apache2/*")
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/navicli.py 0000644 0001750 0001750 00000007170 12625313241 021775 0 ustar caribou caribou # Copyright (C) 2008 EMC Corporation. Keith Kearnan
# Copyright (C) 2014 Red Hat, Inc., Bryn M. Reeves
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin, os
from sos.utilities import is_executable
# Just for completeness sake.
from six.moves import input
class Navicli(Plugin, RedHatPlugin):
""" EMC Navicli
"""
plugin_name = 'navicli'
profiles = ('storage', 'hardware')
def check_enabled(self):
return is_executable("navicli")
def get_navicli_config(self):
""" EMC Navisphere Host Agent NAVICLI specific information - files
"""
self.add_copy_spec([
"/etc/Navisphere/agent.config",
"/etc/Navisphere/Navimon.cfg",
"/etc/Navisphere/Quietmode.cfg",
"/etc/Navisphere/messages/[a-z]*",
"/etc/Navisphere/log/[a-z]*"
])
def get_navicli_SP_info(self, SP_address):
""" EMC Navisphere Host Agent NAVICLI specific
information - CLARiiON - commands
"""
self.add_cmd_output([
"navicli -h %s getall" % SP_address,
"navicli -h %s getsptime -spa" % SP_address,
"navicli -h %s getsptime -spb" % SP_address,
"navicli -h %s getlog" % SP_address,
"navicli -h %s getdisk" % SP_address,
"navicli -h %s getcache" % SP_address,
"navicli -h %s getlun" % SP_address,
"navicli -h %s getlun -rg -type -default -owner -crus "
"-capacity" % SP_address,
"navicli -h %s lunmapinfo" % SP_address,
"navicli -h %s getcrus" % SP_address,
"navicli -h %s port -list -all" % SP_address,
"navicli -h %s storagegroup -list" % SP_address,
"navicli -h %s spportspeed -get" % SP_address
])
def setup(self):
self.get_navicli_config()
CLARiiON_IP_address_list = []
CLARiiON_IP_loop = "stay_in"
while CLARiiON_IP_loop == "stay_in":
try:
ans = input("CLARiiON SP IP Address or [Enter] to exit: ")
except:
return
if self.check_ext_prog("navicli -h %s getsptime" % (ans,)):
CLARiiON_IP_address_list.append(ans)
else:
if ans != "":
print("The IP address you entered, %s, is not to an "
"active CLARiiON SP." % ans)
if ans == "":
CLARiiON_IP_loop = "get_out"
# Sort and dedup the list of CLARiiON IP Addresses
CLARiiON_IP_address_list.sort()
for SP_address in CLARiiON_IP_address_list:
if CLARiiON_IP_address_list.count(SP_address) > 1:
CLARiiON_IP_address_list.remove(SP_address)
for SP_address in CLARiiON_IP_address_list:
if SP_address != "":
print(" Gathering NAVICLI information for %s..." %
SP_address)
self.get_navicli_SP_info(SP_address)
# vim: set et ts=4 sw=4 :
sosreport-3.2+git276-g7da50d6/sos/plugins/cluster.py 0000644 0001750 0001750 00000014022 12625313241 022023 0 ustar caribou caribou # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from sos.plugins import Plugin, RedHatPlugin
import re
import os.path
from glob import glob
from datetime import datetime, timedelta
class Cluster(Plugin, RedHatPlugin):
"""Red Hat Cluster High Availability and GFS2
"""
plugin_name = 'cluster'
profiles = ('cluster',)
option_list = [
("gfs2lockdump", 'gather output of gfs2 lockdumps', 'slow', False),
("crm_from", 'specify the start time for crm_report', 'fast', False),
('lockdump', 'gather dlm lockdumps', 'slow', False),
('crm_scrub', 'enable password scrubbing for crm_report', '', True),
]
packages = [
"luci",
"ricci",
"corosync",
"openais",
"cman",
"clusterlib",
"fence-agents",
"pacemaker"
]
files = ["/etc/cluster/cluster.conf"]
debugfs_path = "/sys/kernel/debug"
_debugfs_cleanup = False
def setup(self):
self.add_copy_spec([
"/etc/cluster.conf",
"/etc/cluster",
"/etc/sysconfig/dlm",
"/etc/sysconfig/pacemaker",
"/etc/sysconfig/cluster",
"/etc/sysconfig/cman",
"/etc/fence_virt.conf",
"/var/lib/ricci",
"/var/lib/luci/data/luci.db",
"/var/lib/luci/etc",
"/var/log/cluster",
"/var/log/luci",
"/sys/fs/gfs2/*/withdraw"
])
if self.get_option('gfs2lockdump'):
if self._mount_debug():
self.add_copy_spec(["/sys/kernel/debug/gfs2/*"])
if self.get_option('lockdump'):
self.do_lockdump()
self.add_cmd_output([
"rg_test test /etc/cluster/cluster.conf",
"fence_tool ls -n",
"gfs_control ls -n",
"dlm_tool log_plock",
"clustat",
"group_tool dump",
"cman_tool services",
"cman_tool nodes",
"cman_tool status",
"ccs_tool lsnode",
"corosync-quorumtool -l",
"corosync-quorumtool -s",
"corosync-cpgtool",
"corosync-objctl",
"gfs_control ls -n",
"gfs_control dump",
"fence_tool dump",
"dlm_tool dump",
"dlm_tool ls -n",
"mkqdisk -L",
"pcs config",
"pcs status",
"pcs property list --all"
])
# crm_report needs to be given a --from "YYYY-MM-DD HH:MM:SS" start
# time in order to collect data.
crm_from = (datetime.today() -
timedelta(hours=72)).strftime("%Y-%m-%d %H:%m:%S")
if self.get_option('crm_from') is not False:
if re.match(r'\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}',
str(self.get_option('crm_from'))):
crm_from = self.get_option('crm_from')
else:
self._log_error(
"crm_from parameter '%s' is not a valid date: using "
"default" % self.get_option('crm_from'))
crm_dest = self.get_cmd_output_path(name='crm_report', make=False)
crm_scrub = '-p "passw.*"'
if not self.get_option("crm_scrub"):
crm_scrub = ''
self._log_warn("scrubbing of crm passwords has been disabled:")
self._log_warn("data collected by crm_report may contain"
" sensitive values.")
self.add_cmd_output('crm_report %s -S -d --dest %s --from "%s"' %
(crm_scrub, crm_dest, crm_from),
chroot=self.tmp_in_sysroot())
def do_lockdump(self):
if self._mount_debug():
dlm_tool = "dlm_tool ls"
result = self.call_ext_prog(dlm_tool)
if result['status'] != 0:
return
lock_exp = r'^name\s+([^\s]+)$'
lock_re = re.compile(lock_exp, re.MULTILINE)
for lockspace in lock_re.findall(result['output']):
self.add_cmd_output(
"dlm_tool lockdebug -svw '%s'" % lockspace,
suggest_filename="dlm_locks_%s" % lockspace
)
def _mount_debug(self):
if not os.path.ismount(self.debugfs_path):
self._debugfs_cleanup = True
r = self.call_ext_prog("mount -t debugfs debugfs %s"
% self.debugfs_path)
if r['status'] != 0:
self._log_error("debugfs not mounted and mount attempt failed")
self._debugfs_cleanup = False
return os.path.ismount(self.debugfs_path)
def postproc(self):
for cluster_conf in glob("/etc/cluster/cluster.conf*"):
self.do_file_sub(
cluster_conf,
r"(\s*\