diff --git a/sos-activemq-collect-logs-config.patch b/sos-activemq-collect-logs-config.patch new file mode 100644 index 0000000..e6f6490 --- /dev/null +++ b/sos-activemq-collect-logs-config.patch @@ -0,0 +1,77 @@ +From e2a94de2e574b61d1da071f961863d2490c90bc0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pep=20Turr=C3=B3=20Mauri?= +Date: Tue, 23 Dec 2014 19:36:29 +0100 +Subject: [PATCH] [activemq] Honour all_logs and get config on RHEL +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Get only current log file by default, allowing full dir +collection via the all_logs option. + +Add a Red Hat version of the plugin that collects the two +main configuration files for activemq. Also enable that plugin +in the OpenShift profile. + +Related: RHBZ#1165878 +Fixes: #457. + +Signed-off-by: Pep TurrĂ³ Mauri +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/activemq.py | 31 ++++++++++++++++++++++++++++--- + 1 file changed, 28 insertions(+), 3 deletions(-) + +diff --git a/sos/plugins/activemq.py b/sos/plugins/activemq.py +index 291fcd9..1594229 100644 +--- a/sos/plugins/activemq.py ++++ b/sos/plugins/activemq.py +@@ -16,17 +16,42 @@ + from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin + + +-class ActiveMq(Plugin, RedHatPlugin, DebianPlugin): ++class ActiveMq(Plugin, DebianPlugin): + """ActiveMQ message broker + """ + + plugin_name = 'activemq' +- profiles = () ++ profiles = ('openshift',) + packages = ('activemq', 'activemq-core') + files = ('/var/log/activemq',) + + def setup(self): +- self.add_copy_spec(list(self.files)) ++ if self.get_option("all_logs"): ++ self.add_copy_spec(list(self.files)) ++ else: ++ self.add_copy_spec([ ++ "/var/log/activemq/activemq.log", ++ "/var/log/activemq/wrapper.log" ++ ]) ++ ++ def postproc(self): ++ # activemq.xml contains credentials in this form: ++ # ++ self.do_file_sub( ++ '/etc/activemq/activemq.xml', ++ r'(\s*password=")[^"]*(".*)', ++ r"\1******\2" ++ ) ++ ++ ++class RedHatActiveMq(ActiveMq, RedHatPlugin): ++ ++ def setup(self): ++ super(RedHatActiveMq, self).setup() ++ self.add_copy_spec([ ++ '/etc/sysconfig/activemq', ++ '/etc/activemq/activemq.xml' ++ ]) + + + class UbuntuActiveMq(ActiveMq, UbuntuPlugin): +-- +1.8.3.1 + diff --git a/sos-add-support-for-tomcat7.patch b/sos-add-support-for-tomcat7.patch new file mode 100644 index 0000000..372e887 --- /dev/null +++ b/sos-add-support-for-tomcat7.patch @@ -0,0 +1,48 @@ +From 874cc7d0889adf32b8c36bb218212d3304d43d5b Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Mon, 20 Oct 2014 09:13:07 +0100 +Subject: [PATCH] [tomcat] add support for tomcat7 and log size limits + +Based on a patch from Pavel Moravec in Issue #412. + +Fixes #412. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/tomcat.py | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/sos/plugins/tomcat.py b/sos/plugins/tomcat.py +index b7aea2c..4f78c1d 100644 +--- a/sos/plugins/tomcat.py ++++ b/sos/plugins/tomcat.py +@@ -22,17 +22,21 @@ class Tomcat(Plugin, RedHatPlugin): + plugin_name = 'tomcat' + profiles = ('webserver', 'java', 'services') + +- packages = ('tomcat6',) ++ packages = ('tomcat6', 'tomcat') + + def setup(self): + self.add_copy_spec([ +- "/etc/tomcat6", +- "/var/log/tomcat6/catalina.out" ++ "/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_file_sub( +- "/etc/tomcat6/tomcat-users.xml", ++ self.do_path_regex_sub( ++ r"\/etc\/tomcat.*\/tomcat-users.xml", + r"password=(\S*)", + r'password="********"' + ) +-- +1.9.3 + diff --git a/sos-anaconda-make-useradd-password-regex-tolerant.patch b/sos-anaconda-make-useradd-password-regex-tolerant.patch new file mode 100644 index 0000000..e7b5f5e --- /dev/null +++ b/sos-anaconda-make-useradd-password-regex-tolerant.patch @@ -0,0 +1,26 @@ +From 5a97e0e2571b948f1f7bc602e6f190976de99eee Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Tue, 13 Jan 2015 16:31:58 +0000 +Subject: [PATCH] [anaconda] make useradd password regex tolerant of whitespace + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/anaconda.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sos/plugins/anaconda.py b/sos/plugins/anaconda.py +index 08d300b..aea3300 100644 +--- a/sos/plugins/anaconda.py ++++ b/sos/plugins/anaconda.py +@@ -54,7 +54,7 @@ class Anaconda(Plugin, RedHatPlugin): + ) + self.do_file_sub( + "/root/anaconda-ks.cfg", +- r"(user.*--password=*)(\S*)", ++ r"(user.*--password=*\s*)\s*(\S*)", + r"\1********" + ) + +-- +1.9.3 + diff --git a/sos-call-rhsm-debug-with-no-subscriptions.patch b/sos-call-rhsm-debug-with-no-subscriptions.patch new file mode 100644 index 0000000..4e97a53 --- /dev/null +++ b/sos-call-rhsm-debug-with-no-subscriptions.patch @@ -0,0 +1,26 @@ +From e8428d458cfd65bdc34d69f32db0bf4f5aca7540 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Thu, 2 Oct 2014 17:16:55 +0100 +Subject: [PATCH] [yum] call rhsm-debug with --no-subscriptions + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/yum.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sos/plugins/yum.py b/sos/plugins/yum.py +index 7dac5e4..816e2b0 100644 +--- a/sos/plugins/yum.py ++++ b/sos/plugins/yum.py +@@ -54,7 +54,7 @@ class Yum(Plugin, RedHatPlugin): + "subscription-manager list --consumed" + ]) + self.add_cmd_output("rhsm-debug system --sos --no-archive " +- "--destination %s" ++ "--no-subscriptions --destination %s" + % self.get_cmd_output_path()) + + if self.get_option("yumlist"): +-- +1.9.3 + diff --git a/sos-ceph-add-calamari-rados.patch b/sos-ceph-add-calamari-rados.patch new file mode 100644 index 0000000..ed9dfcb --- /dev/null +++ b/sos-ceph-add-calamari-rados.patch @@ -0,0 +1,93 @@ +From 24ecc933d109c0eba120b434d08aa560e9a56869 Mon Sep 17 00:00:00 2001 +From: Pavel Moravec +Date: Wed, 1 Jul 2015 12:15:41 +0200 +Subject: [PATCH 1/2] [ceph] add logs, report and calamari conf + +Update ceph commands and add log and configuration file +collection for calamari and radosgw. + +Resolves: #496 +Resolves: rhbz#1210527 + +Signed-off-by: Brad Hubbard +Signed-off-by: Pavel Moravec +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/ceph.py | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/sos/plugins/ceph.py b/sos/plugins/ceph.py +index 52b8fff..0bfdbe0 100644 +--- a/sos/plugins/ceph.py ++++ b/sos/plugins/ceph.py +@@ -37,17 +37,22 @@ class Ceph(Plugin, RedHatPlugin, UbuntuPlugin): + def setup(self): + self.add_copy_spec([ + "/etc/ceph/", +- "/var/log/ceph/" ++ "/var/log/ceph/", ++ "/etc/calamari/", ++ "/var/log/calamari", ++ "/var/log/radosgw" + ]) + + self.add_cmd_output([ + "ceph status", +- "ceph health", ++ "ceph health detail", + "ceph osd tree", + "ceph osd stat", + "ceph osd dump", + "ceph mon stat", +- "ceph mon dump" ++ "ceph mon dump", ++ "ceph df", ++ "ceph report" + ]) + + self.add_forbidden_path("/etc/ceph/*keyring") +-- +1.8.3.1 + + +From 696f3c605c5d6b0cb8c0703635401991bc7af934 Mon Sep 17 00:00:00 2001 +From: Pavel Moravec +Date: Thu, 2 Jul 2015 13:10:31 +0200 +Subject: [PATCH 2/2] [ceph] add calamari-server and librados2 to the package + list + +Enable ceph plugin also by either calamari-server or librados2 +package. + +This ensures Calamari and Rados log collection is effective +regardless of which packages are installed on a given system. + +This is a temporary solution until rados is split from the ceph +package. + +Resolves: #496 + +Signed-off-by: Pavel Moravec +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/ceph.py | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/sos/plugins/ceph.py b/sos/plugins/ceph.py +index 0bfdbe0..e9db4c6 100644 +--- a/sos/plugins/ceph.py ++++ b/sos/plugins/ceph.py +@@ -31,7 +31,9 @@ class Ceph(Plugin, RedHatPlugin, UbuntuPlugin): + 'ceph-mds', + 'ceph-common', + 'libcephfs1', +- 'ceph-fs-common' ++ 'ceph-fs-common', ++ 'calamari-server', ++ 'librados2' + ) + + def setup(self): +-- +1.8.3.1 + diff --git a/sos-ceph-collect-var-lib-var-run.patch b/sos-ceph-collect-var-lib-var-run.patch new file mode 100644 index 0000000..45d6ff9 --- /dev/null +++ b/sos-ceph-collect-var-lib-var-run.patch @@ -0,0 +1,44 @@ +From 6b4b361c8b4814160d6fab2fb447f28957977e95 Mon Sep 17 00:00:00 2001 +From: Pavel Moravec +Date: Fri, 27 Nov 2015 12:43:33 +0100 +Subject: [PATCH] [ceph] Collect (parts of) /var/lib/ceph and /var/run/ceph + +Collect the two directories without some forbidden paths. + +Reorder self.add_forbidden_path(..) to have some logical ordering there. + +Resolves: #693 + +Signed-off-by: Pavel Moravec +--- + sos/plugins/ceph.py | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/sos/plugins/ceph.py b/sos/plugins/ceph.py +index 6ccb930..10fee88 100644 +--- a/sos/plugins/ceph.py ++++ b/sos/plugins/ceph.py +@@ -40,6 +40,8 @@ class Ceph(Plugin, RedHatPlugin, UbuntuPlugin): + self.add_copy_spec([ + "/etc/ceph/", + "/var/log/ceph/", ++ "/var/lib/ceph/", ++ "/var/run/ceph/", + "/etc/calamari/", + "/var/log/calamari", + "/var/log/radosgw" +@@ -58,7 +60,10 @@ class Ceph(Plugin, RedHatPlugin, UbuntuPlugin): + ]) + + self.add_forbidden_path("/etc/ceph/*keyring") +- self.add_forbidden_path("/var/lib/ceph/*/*keyring") + self.add_forbidden_path("/var/lib/ceph/*keyring") ++ self.add_forbidden_path("/var/lib/ceph/*/*keyring") ++ self.add_forbidden_path("/var/lib/ceph/*/*/*keyring") ++ self.add_forbidden_path("/var/lib/ceph/osd/*") ++ self.add_forbidden_path("/var/lib/ceph/osd/mon/*") + + # vim: et ts=4 sw=4 +-- +2.4.3 + diff --git a/sos-chrony-new-plugin.patch b/sos-chrony-new-plugin.patch new file mode 100644 index 0000000..53e40df --- /dev/null +++ b/sos-chrony-new-plugin.patch @@ -0,0 +1,64 @@ +From b6e6a4d1ce4beae74cb0123bd7c48d0828d120ec Mon Sep 17 00:00:00 2001 +From: Justin Stephenson +Date: Sun, 29 Mar 2015 22:58:42 +0200 +Subject: [PATCH] [chrony] add chrony plugin + +Resolves #539 + +Signed-off-by: Justin Stephenson +Signed-off-by: Pavel Moravec +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/chrony.py | 40 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 40 insertions(+) + create mode 100644 sos/plugins/chrony.py + +diff --git a/sos/plugins/chrony.py b/sos/plugins/chrony.py +new file mode 100644 +index 0000000..d2404d4 +--- /dev/null ++++ b/sos/plugins/chrony.py +@@ -0,0 +1,40 @@ ++# 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 Chrony(Plugin, RedHatPlugin): ++ """Chrony clock (for Network time protocol) ++ """ ++ ++ plugin_name = "chrony" ++ profiles = ('system', 'services') ++ ++ packages = ('chrony',) ++ ++ def setup(self): ++ self.add_copy_spec([ ++ "/etc/chrony.conf", ++ "/var/lib/chrony/drift" ++ ]) ++ self.add_cmd_output([ ++ "chronyc tracking", ++ "chronyc sources", ++ "chronyc sourcestats", ++ "chronyc clients", ++ "journalctl -u chronyd" ++ ]) ++ ++# vim: et ts=4 sw=4 +-- +1.8.3.1 + diff --git a/sos-cluster-crm-report-password-sanitize.patch b/sos-cluster-crm-report-password-sanitize.patch new file mode 100644 index 0000000..a860393 --- /dev/null +++ b/sos-cluster-crm-report-password-sanitize.patch @@ -0,0 +1,62 @@ +From 0d2dd0d9ccc3242dd2dd4513924c8f308000242e Mon Sep 17 00:00:00 2001 +From: Shane Bradley +Date: Wed, 6 May 2015 15:47:07 -0400 +Subject: [PATCH] [cluster] enable crm_report password scrubbing + +Default to specifying a password pattern of 'passw.*' when calling +the crm_report script. This causes matching strings to be elided +from the report data. + +Since this scrubbing can affect the use of pacemaker state machine +snapshots for debugging the behaviour is controlled by a new option +that defaults to enabled: cluster.crm_scrub + +This can be used to obtain an sosreport containing virgin crm_report +data with no password scrubbing: + + # sosreport -k cluster.crm_scrub=False + +Signed-off-by: Shane Bradley +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/cluster.py | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/sos/plugins/cluster.py b/sos/plugins/cluster.py +index 8dd9a4d..084c030 100644 +--- a/sos/plugins/cluster.py ++++ b/sos/plugins/cluster.py +@@ -25,10 +25,12 @@ class Cluster(Plugin, RedHatPlugin): + + 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) ++ ('lockdump', 'gather dlm lockdumps', 'slow', False), ++ ('crm_scrub', 'enable password scrubbing for crm_report', '', True), + ] + + packages = [ +@@ -112,8 +114,14 @@ class Cluster(Plugin, RedHatPlugin): + "default" % self.get_option('crm_from')) + + crm_dest = self.get_cmd_output_path(name='crm_report', make=False) +- self.add_cmd_output('crm_report -S -d --dest %s --from "%s"' +- % (crm_dest, crm_from)) ++ 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)) + + def do_lockdump(self): + if self._mount_debug(): +-- +1.8.3.1 + diff --git a/sos-cluster-crmreport-create-dir.patch b/sos-cluster-crmreport-create-dir.patch new file mode 100644 index 0000000..3453e19 --- /dev/null +++ b/sos-cluster-crmreport-create-dir.patch @@ -0,0 +1,31 @@ +From 147c496d5b2a33b7534ac66dbfb7705ae7ccb7bd Mon Sep 17 00:00:00 2001 +From: Shane Bradley +Date: Wed, 11 Mar 2015 09:55:06 -0400 +Subject: [PATCH] [cluster] crm_report fails to run because dir already exists + +Do not create directory for the destination path used by crm_report. + +Resolves: rhbz#1200526 + +Signed-off-by: Shane Bradley +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/cluster.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sos/plugins/cluster.py b/sos/plugins/cluster.py +index bd2cf8a..8dd9a4d 100644 +--- a/sos/plugins/cluster.py ++++ b/sos/plugins/cluster.py +@@ -111,7 +111,7 @@ class Cluster(Plugin, RedHatPlugin): + "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') ++ crm_dest = self.get_cmd_output_path(name='crm_report', make=False) + self.add_cmd_output('crm_report -S -d --dest %s --from "%s"' + % (crm_dest, crm_from)) + +-- +1.8.3.1 + diff --git a/sos-cluster-data-ownership.patch b/sos-cluster-data-ownership.patch new file mode 100644 index 0000000..0ccabaa --- /dev/null +++ b/sos-cluster-data-ownership.patch @@ -0,0 +1,188 @@ +From bb1e81e0d3d738f2f333175fc32987ed473edd8d Mon Sep 17 00:00:00 2001 +From: Shane Bradley +Date: Fri, 6 Feb 2015 11:24:26 -0500 +Subject: [PATCH] [cluster] remove some files and commands that are no longer + needed + +Removed some of the files and commands that are no longer needed on +RHEL6+. In addition, the gfs_lockdump option did not capture gfs2 lock +dumps. The option is now called gfs2_lockdump and will mount the +/sys/kernel/debug directory and the gfs2 lockdumps will be copied from +that mount point. + +In addition added a couple files that are needed for pacemaker/dlm. + +Resolves: rhbz#1083656 + +Signed-off-by: Shane Bradley +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/cluster.py | 66 +++++++++++++++++++++++++++++--------------------- + 1 file changed, 39 insertions(+), 27 deletions(-) + +diff --git a/sos/plugins/cluster.py b/sos/plugins/cluster.py +index 9b5eb22..a84d3e2 100644 +--- a/sos/plugins/cluster.py ++++ b/sos/plugins/cluster.py +@@ -14,18 +14,19 @@ + + 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 Suite and GFS ++ """Red Hat Cluster High Availability and GFS2 + """ + + plugin_name = 'cluster' + profiles = ('cluster',) + option_list = [ +- ("gfslockdump", 'gather output of gfs lockdumps', 'slow', False), ++ ("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) + ] +@@ -42,12 +43,16 @@ class Cluster(Plugin, RedHatPlugin): + + 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.xml", + "/etc/cluster", ++ "/etc/sysconfig/dlm", ++ "/etc/sysconfig/pacemaker", + "/etc/sysconfig/cluster", + "/etc/sysconfig/cman", + "/etc/fence_virt.conf", +@@ -56,12 +61,12 @@ class Cluster(Plugin, RedHatPlugin): + "/var/lib/luci/etc", + "/var/log/cluster", + "/var/log/luci", +- "/etc/fence_virt.conf", + "/sys/fs/gfs2/*/withdraw" + ]) + +- if self.get_option('gfslockdump'): +- self.do_gfslockdump() ++ 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() +@@ -81,7 +86,6 @@ class Cluster(Plugin, RedHatPlugin): + "corosync-quorumtool -s", + "corosync-cpgtool", + "corosync-objctl", +- "group_tool ls -g1", + "gfs_control ls -n", + "gfs_control dump", + "fence_tool dump", +@@ -108,26 +112,29 @@ class Cluster(Plugin, RedHatPlugin): + % (crm_dest, crm_from)) + + def do_lockdump(self): +- 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 do_gfslockdump(self): +- mnt_exp = r'^\S+\s+([^\s]+)\s+gfs\s+.*$' +- for mnt in self.do_regex_find_all(mnt_exp, "/proc/mounts"): +- self.add_cmd_output( +- "gfs_tool lockdump %s" % mnt, +- suggest_filename="gfs_lockdump_" + self.mangle_command(mnt) +- ) ++ 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*"): +@@ -148,6 +155,11 @@ class Cluster(Plugin, RedHatPlugin): + r"(.*fence.*\.passwd=)(.*)", + r"\1******" + ) ++ if self._debugfs_cleanup and os.path.ismount(self.debugfs_path): ++ r = self.call_ext_prog("umount %s" % self.debugfs_path) ++ if r['status'] != 0: ++ self._log_error("could not unmount %s" % self.debugfs_path) ++ + return + + # vim: et ts=4 sw=4 +-- +1.8.3.1 + +From 55aebeabb2d2c87c695041cff426afaa6bd2808a Mon Sep 17 00:00:00 2001 +From: Shane Bradley +Date: Tue, 17 Feb 2015 13:54:01 -0500 +Subject: [PATCH] [cluster] add a couple pcs commands to the cluster plugin + +There are 3 pcs commands added to cluster plugin to get +information about the status of pacemaker cluster. + +Signed-off-by: Shane Bradley +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/cluster.py | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/sos/plugins/cluster.py b/sos/plugins/cluster.py +index 7aeed44..bd2cf8a 100644 +--- a/sos/plugins/cluster.py ++++ b/sos/plugins/cluster.py +@@ -92,7 +92,10 @@ class Cluster(Plugin, RedHatPlugin): + "fence_tool dump", + "dlm_tool dump", + "dlm_tool ls -n", +- "mkqdisk -L" ++ "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 +-- +1.8.3.1 + diff --git a/sos-cluster-enable-when-luci-only.patch b/sos-cluster-enable-when-luci-only.patch new file mode 100644 index 0000000..736c1dd --- /dev/null +++ b/sos-cluster-enable-when-luci-only.patch @@ -0,0 +1,33 @@ +From f5211fd8725629e23a3a0f802bd6e635290dab36 Mon Sep 17 00:00:00 2001 +From: Shane Bradley +Date: Tue, 10 Feb 2015 10:42:39 -0500 +Subject: [PATCH] [cluster] add luci to packages for standalone luci servers + +A host with only luci package installed would not collect luci logs +because the cluster plugin would not run since none of the packages +were found. This patch adds luci to the package set required for the +plugin to run. + +Resolves: rhbz#1171186 + +Signed-off-by: Shane Bradley +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/cluster.py | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sos/plugins/cluster.py b/sos/plugins/cluster.py +index a84d3e2..7aeed44 100644 +--- a/sos/plugins/cluster.py ++++ b/sos/plugins/cluster.py +@@ -32,6 +32,7 @@ class Cluster(Plugin, RedHatPlugin): + ] + + packages = [ ++ "luci", + "ricci", + "corosync", + "openais", +-- +1.8.3.1 + diff --git a/sos-collect-docker-daemon-logs.patch b/sos-collect-docker-daemon-logs.patch new file mode 100644 index 0000000..03450e1 --- /dev/null +++ b/sos-collect-docker-daemon-logs.patch @@ -0,0 +1,65 @@ +From 4edd40d584879ebd81bce88f04bc294789175eb0 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Wed, 7 Oct 2015 12:56:55 +0100 +Subject: [PATCH 1/2] [kubernetes] do not reverse-sort journald logs + +Drop the '-r' when obtaining logs from journald to be consistent +with other plugins: users can sort log entries in whatever order +they prefer on the analysis system. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/kubernetes.py | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/sos/plugins/kubernetes.py b/sos/plugins/kubernetes.py +index 59b6b53..3399b2e 100644 +--- a/sos/plugins/kubernetes.py ++++ b/sos/plugins/kubernetes.py +@@ -35,11 +35,11 @@ class kubernetes(Plugin, RedHatPlugin): + 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 -r -u kubelet") +- self.add_cmd_output("journalctl -r -u kube-apiserver") +- self.add_cmd_output("journalctl -r -u kube-controller-manager") +- self.add_cmd_output("journalctl -r -u kube-scheduler") +- self.add_cmd_output("journalctl -r -u kube-proxy") ++ 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") +-- +1.8.3.1 + +From 3ce984a7d220669eaf2e6c08d983679183fb55fe Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Wed, 7 Oct 2015 13:03:45 +0100 +Subject: [PATCH 2/2] [docker] collect journald logs for docker unit + +Fixes: #609. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/docker.py | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sos/plugins/docker.py b/sos/plugins/docker.py +index c5ea8a0..aab558d 100644 +--- a/sos/plugins/docker.py ++++ b/sos/plugins/docker.py +@@ -34,6 +34,7 @@ class Docker(Plugin): + ]) + + 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) +-- +1.8.3.1 + diff --git a/sos-corosync-add-postprocessing-for-corosync-objctl.patch b/sos-corosync-add-postprocessing-for-corosync-objctl.patch new file mode 100644 index 0000000..f76548b --- /dev/null +++ b/sos-corosync-add-postprocessing-for-corosync-objctl.patch @@ -0,0 +1,35 @@ +From 77ea53cf7c13c59c2a1f4608d59e1b9e8f4da835 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Wed, 15 Oct 2014 15:57:47 +0100 +Subject: [PATCH] [corosync] add postprocessing for corosync-objctl output + +The corosync-objctl command may include fence device passwords in +its output. Remove them with the same postprocessing regex as the +cluster plugin uses. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/corosync.py | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/sos/plugins/corosync.py b/sos/plugins/corosync.py +index 2cd22c3..db9b547 100644 +--- a/sos/plugins/corosync.py ++++ b/sos/plugins/corosync.py +@@ -40,6 +40,13 @@ class Corosync(Plugin): + ]) + self.call_ext_prog("killall -USR2 corosync") + ++ def postproc(self): ++ self.do_cmd_output_sub( ++ "corosync-objctl", ++ r"(.*fence.*\.passwd=)(.*)", ++ r"\1******" ++ ) ++ + + class RedHatCorosync(Corosync, RedHatPlugin): + +-- +1.9.3 + diff --git a/sos-ctdb-fix-redhatplugin-tagging-use.patch b/sos-ctdb-fix-redhatplugin-tagging-use.patch new file mode 100644 index 0000000..9164028 --- /dev/null +++ b/sos-ctdb-fix-redhatplugin-tagging-use.patch @@ -0,0 +1,42 @@ +From 12ec2a4643c844a7a9bf46f3d9557e38f0ae7403 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Mon, 19 Jan 2015 18:47:03 +0000 +Subject: [PATCH] [ctdb] fix RedHatPlugin tagging use + +The generic Ctdb class is tagged with RedHatPlugin. This causes +the RedHatCtdb to not execute (since only the first matching class +is instantiated). + +Remove the RedHatPlugin tag from the Ctdb class and fix the +former's call to Ctdb.setup(). + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/ctdb.py | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/sos/plugins/ctdb.py b/sos/plugins/ctdb.py +index 443181c..e1bd78e 100644 +--- a/sos/plugins/ctdb.py ++++ b/sos/plugins/ctdb.py +@@ -16,7 +16,7 @@ + from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin + + +-class Ctdb(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin): ++class Ctdb(Plugin, DebianPlugin, UbuntuPlugin): + """Samba Clustered TDB + """ + packages = ('ctdb',) +@@ -45,7 +45,7 @@ class Ctdb(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin): + + class RedHatCtdb(Ctdb, RedHatPlugin): + def setup(self): +- super(RedHatCtdb, self).super() ++ super(RedHatCtdb, self).setup() + self.add_copy_spec("/etc/sysconfig/ctdb") + + # vim: et ts=4 sw=4 +-- +1.9.3 + diff --git a/sos-disable-the-zip-compression-type.patch b/sos-disable-the-zip-compression-type.patch new file mode 100644 index 0000000..7d3dfd7 --- /dev/null +++ b/sos-disable-the-zip-compression-type.patch @@ -0,0 +1,60 @@ +From 081e1ce9f9ad7570d057babd81b474fd407149d7 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Tue, 9 Dec 2014 17:32:45 +0000 +Subject: [PATCH] [sosreport] disable the 'zip' compression type + +The Zip archive format is little used and has been broken for +some time: + + Unexpected exception setting up archive: + Traceback (most recent call last): + File "/usr/lib/python2.7/site-packages/sos/sosreport.py", line 1092, in prework + self._set_archive() + File "/usr/lib/python2.7/site-packages/sos/sosreport.py", line 679, in _set_archive + self.archive = ZipFileArchive(archive_name, self.tmpdir) + TypeError: __init__() takes exactly 2 arguments (3 given) + __init__() takes exactly 2 arguments (3 given) + +Remove it from the allowed options list for --compression-type. + +The supporting Archive classes can be removed in a separate commit. + +Signed-off-by: Bryn M. Reeves +--- + sos/sosreport.py | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/sos/sosreport.py b/sos/sosreport.py +index 99b5f47..a697380 100644 +--- a/sos/sosreport.py ++++ b/sos/sosreport.py +@@ -599,7 +599,7 @@ class SoSOptions(object): + dest="report", + help="Disable HTML/XML reporting", default=False) + parser.add_option("-z", "--compression-type", dest="compression_type", +- help="compression technology to use [auto, zip, " ++ help="compression technology to use [auto, " + "gzip, bzip2, xz] (default=auto)", + default="auto") + +@@ -675,8 +675,6 @@ class SoSReport(object): + if self.opts.compression_type == 'auto': + auto_archive = self.policy.get_preferred_archive() + self.archive = auto_archive(archive_name, self.tmpdir) +- elif self.opts.compression_type == 'zip': +- self.archive = ZipFileArchive(archive_name, self.tmpdir) + else: + self.archive = TarFileArchive(archive_name, self.tmpdir) + self.archive.set_debug(True if self.opts.debug else False) +@@ -1080,7 +1078,7 @@ class SoSReport(object): + self.policy.pre_work() + try: + self.ui_log.info(_(" Setting up archive ...")) +- compression_methods = ('auto', 'zip', 'bzip2', 'gzip', 'xz') ++ compression_methods = ('auto', 'bzip2', 'gzip', 'xz') + method = self.opts.compression_type + if method not in compression_methods: + compression_list = ', '.join(compression_methods) +-- +1.9.3 + diff --git a/sos-docs-update-man-page-for-new-options.patch b/sos-docs-update-man-page-for-new-options.patch new file mode 100644 index 0000000..a05d692 --- /dev/null +++ b/sos-docs-update-man-page-for-new-options.patch @@ -0,0 +1,91 @@ +From 0be76caf77b53ce2726cb419262ceb8f52081c9e Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Wed, 17 Dec 2014 13:01:03 +0000 +Subject: [PATCH] [docs] update man page for new options + +The man page was missing: + + --verify + --all-logs + --log-size + --plugin-option + +And listed the old '--ticket' (now --ticket-number). + +Signed-off-by: Bryn M. Reeves +--- + man/en/sosreport.1 | 29 +++++++++++++++++++++++++---- + 1 file changed, 25 insertions(+), 4 deletions(-) + +diff --git a/man/en/sosreport.1 b/man/en/sosreport.1 +index 88589cf..1066b1d 100644 +--- a/man/en/sosreport.1 ++++ b/man/en/sosreport.1 +@@ -8,14 +8,19 @@ sosreport \- Collect and package diagnostic and support data + [-e|--enable-plugins plugin-names]\fR + [-o|--only-plugins plugin-names]\fR + [-a|--alloptions] [-v|--verbose]\fR ++ [-k plug.opt|--plugin-option plug.opt]\fR + [--no-report] [--config-file conf]\fR + [--batch] [--build] [--debug]\fR + [--name name] [--case-id id] [--ticket-number nr] + [--tmp-dir directory]\fR + [-p|--profile profile-name]\fR + [--list-profiles]\fR ++ [--verify]\fR ++ [--log-size]\fR ++ [--all-logs]\fR + [-z|--compression-type method]\fR +- [--help]\fR ++ [-h|--help]\fR ++ + .SH DESCRIPTION + \fBsosreport\fR generates an archive of configuration and diagnostic + information from the running system. The archive may be stored locally +@@ -46,7 +51,7 @@ Enable the specified plugin(s) only (all other plugins should be + disabled). Multiple plugins may be specified by repeating the option + or as a comma-separated list. + .TP +-.B \-k PLUGNAME.PLUGOPT[=VALUE] ++.B \-k PLUGNAME.PLUGOPT[=VALUE], \--plugin-option=PLUGNAME.PLUGOPT[=VALUE] + Specify plug-in options. The option PLUGOPT is enabled, or set to the + specified value in the plug-in PLUGNAME. + .TP +@@ -81,6 +86,22 @@ profiles include: boot, cluster, desktop, debug, hardware, identity, + network, openstack, packagemanager, security, services, storage, + sysmgmt, system, performance, virt, and webserver. + .TP ++.B \--verify ++Instructs plugins to perform plugin-specific verification during data ++collection. This may include package manager verification, log integrity ++testing or other plugin defined behaviour. Use of \--verify may cause ++the time taken to generate a report to be considerably longer. ++.TP ++.B \--log-size ++Places a global limit on the size of any collected set of logs. The ++limit is applied separately for each set of logs collected by any ++plugin. ++.TP ++.B \--all-logs ++Tell plugins to collect all possible log data ignoring any size limits ++and including logs in non-default locations. This option may significantly ++increase the size of reports. ++.TP + .B \-z, \--compression-type METHOD + Override the default compression type specified by the active policy. + .TP +@@ -94,9 +115,9 @@ Specify a name to be used for the archive. + .B \--case-id NUMBER + Specify a case identifier to associate with the archive. + Identifiers may include alphanumeric characters, commas and periods ('.'). +-Synonymous with \--ticket, \--ticket-number. ++Synonymous with \--ticket-number. + .TP +-.B \--ticket, \--ticket-number NUMBER ++.B \--ticket-number NUMBER + Specify a ticket number or other identifier to associate with the archive. + Identifiers may include alphanumeric characters, commas and periods ('.'). + Synonymous with \--case-id. +-- +1.9.3 + diff --git a/sos-fix-exception-when-networkmanager-disabled.patch b/sos-fix-exception-when-networkmanager-disabled.patch new file mode 100644 index 0000000..d24a030 --- /dev/null +++ b/sos-fix-exception-when-networkmanager-disabled.patch @@ -0,0 +1,46 @@ +From d19bc046d549aaf634314a257dd22623df731648 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Tue, 3 Mar 2015 14:54:48 +0000 +Subject: [PATCH] [networking] test nmcli status before using output + +The networking module assumes that nmcli commands succeed if the +results object is not None; this is not valid and will lead to +errors in subsequent commands if the call returned an error +message instead of the expected content: + + [plugin:networking] collecting output of 'nmcli con show conf 'Error: nmcli (0.9.10.0) and NetworkManager (unknown) versions don't match. Force execution using --nocheck, but the results are unpredictable.'' + Traceback (most recent call last): + File "/usr/sbin/sosreport", line 25, in + main(sys.argv[1:]) + File "/usr/lib/python2.7/site-packages/sos/sosreport.py", line 1459, in main + sos.execute() + ValueError: No closing quotation + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/networking.py | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/sos/plugins/networking.py b/sos/plugins/networking.py +index 9f6ece0..ae6cb1b 100644 +--- a/sos/plugins/networking.py ++++ b/sos/plugins/networking.py +@@ -142,13 +142,13 @@ class Networking(Plugin): + + nmcli_con_show_result = self.call_ext_prog( + "nmcli --terse --fields NAME con show") +- if nmcli_con_show_result: ++ if nmcli_con_show_result['status'] == 0: + for con in nmcli_con_show_result['output'].splitlines(): + self.add_cmd_output("nmcli con show conf '%s'" % con) + + nmcli_dev_status_result = self.call_ext_prog( + "nmcli --terse --fields DEVICE dev status") +- if nmcli_dev_status_result: ++ if nmcli_dev_status_result['status'] == 0: + for dev in nmcli_dev_status_result['output'].splitlines(): + self.add_cmd_output("nmcli device show "+dev) + +-- +1.8.3.1 + diff --git a/sos-fix-kpatch-force-enabled.patch b/sos-fix-kpatch-force-enabled.patch new file mode 100644 index 0000000..aa8ef94 --- /dev/null +++ b/sos-fix-kpatch-force-enabled.patch @@ -0,0 +1,33 @@ +From 6b43c42078604b0551923c2801108848e97ba3b9 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Tue, 14 Oct 2014 15:43:20 +0100 +Subject: [PATCH] [kpatch] do not try to read kpatch data if it could not be + run + +Everything the kpatch plugin does requires the list of available +kpatch patches obtained from 'kpatch list'. If this fails return +immediately from the setup method. + +Fixes #417. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/kpatch.py | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sos/plugins/kpatch.py b/sos/plugins/kpatch.py +index 7909926..6ef557e 100644 +--- a/sos/plugins/kpatch.py ++++ b/sos/plugins/kpatch.py +@@ -27,6 +27,8 @@ class Kpatch(Plugin, RedHatPlugin): + + def setup(self): + kpatch_list = self.get_cmd_output_now("kpatch list") ++ if not kpatch_list: ++ return + kpatches = open(kpatch_list, "r").read().splitlines() + for patch in kpatches: + if not re.match("^kpatch-.*\(.*\)", patch): +-- +1.9.3 + diff --git a/sos-hpasm-no-data-timeout.patch b/sos-hpasm-no-data-timeout.patch new file mode 100644 index 0000000..731097d --- /dev/null +++ b/sos-hpasm-no-data-timeout.patch @@ -0,0 +1,35 @@ +From 61a5b47d4fe4fd47e759b9acc19483491ec17005 Mon Sep 17 00:00:00 2001 +From: Pavel Moravec +Date: Tue, 5 May 2015 13:50:55 +0200 +Subject: [PATCH] [hpasm] hpasmcli commands hang under timeout + +When hpasmcli is run in a python Popen or system pipeline via the +timeout command it hangs indefinitely. + +Work around this temporarily by disabling the use of the timeout +program (by passing a zero timeout value) when running this +command. + +Fixes: #559 + +Signed-off-by: Pavel Moravec +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/hpasm.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sos/plugins/hpasm.py b/sos/plugins/hpasm.py +index 4d5d158..4d70887 100644 +--- a/sos/plugins/hpasm.py ++++ b/sos/plugins/hpasm.py +@@ -30,6 +30,6 @@ class Hpasm(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin): + self.add_cmd_output([ + "hpasmcli -s 'show asr'", + "hpasmcli -s 'show server'" +- ]) ++ ], timeout=0) + + # vim: et ts=4 sw=4 +-- +1.8.3.1 + diff --git a/sos-html-report-generate.patch b/sos-html-report-generate.patch new file mode 100644 index 0000000..a87f0ea --- /dev/null +++ b/sos-html-report-generate.patch @@ -0,0 +1,84 @@ +From c607cac7256ced5d1396ae61591f9eae4a9d385f Mon Sep 17 00:00:00 2001 +From: Pavel Moravec +Date: Fri, 18 Sep 2015 09:25:39 +0200 +Subject: [PATCH] [sosreport] fix command-line report defaults + +opts.report is True regardless of using --no-report option or not. That +means the test "if not self.opts.report:" to decide generation of +reports is evaluated to False every time and no report is generated any +time. + +This commit renames opts.report and SoSOptions._report to noreport (to +get rid of the variable name confusion) and updates default value +accordingly. + +Resolves #625 +Closes #644 + +Signed-off-by: Pavel Moravec +Signed-off-by: Adam Stokes +--- + sos/sosreport.py | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +diff --git a/sos/sosreport.py b/sos/sosreport.py +index 02d8a32..a1f1b96 100644 +--- a/sos/sosreport.py ++++ b/sos/sosreport.py +@@ -250,7 +250,7 @@ class SoSOptions(object): + _list_profiles = False + _config_file = "" + _tmp_dir = "" +- _report = True ++ _noreport = False + _sysroot = None + _chroot = 'auto' + _compression_type = 'auto' +@@ -522,17 +522,17 @@ class SoSOptions(object): + self._tmp_dir = value + + @property +- def report(self): ++ def noreport(self): + if self._options is not None: +- return self._options.report +- return self._report ++ return self._options.noreport ++ return self._noreport + +- @report.setter +- def report(self, value): ++ @noreport.setter ++ def noreport(self, value): + self._check_options_initialized() + if not isinstance(value, bool): +- raise TypeError("SoSOptions.report expects a boolean") +- self._report = value ++ raise TypeError("SoSOptions.noreport expects a boolean") ++ self._noreport = value + + @property + def sysroot(self): +@@ -646,8 +646,8 @@ class SoSOptions(object): + help="specify alternate temporary directory", + default=None) + parser.add_option("--no-report", action="store_true", +- dest="report", +- help="Disable HTML/XML reporting", default=False) ++ dest="noreport", ++ help="Disable HTML/XML reporting", default=False) + parser.add_option("-s", "--sysroot", action="store", dest="sysroot", + help="system root directory path (default='/')", + default=None) +@@ -1499,7 +1499,7 @@ class SoSReport(object): + self.prework() + self.setup() + self.collect() +- if not self.opts.report: ++ if not self.opts.noreport: + self.report() + self.html_report() + self.plain_report() +-- +1.8.3.1 + diff --git a/sos-httpd-collect-conf-modules.patch b/sos-httpd-collect-conf-modules.patch new file mode 100644 index 0000000..7f8801f --- /dev/null +++ b/sos-httpd-collect-conf-modules.patch @@ -0,0 +1,28 @@ +From b43460ecaeb7e332a993fb6ea19f4808d759711f Mon Sep 17 00:00:00 2001 +From: Coty Sutherland +Date: Thu, 28 May 2015 10:22:39 -0400 +Subject: [PATCH] [apache] Added collection of conf.modules.d dir for httpd 2.4 + +Signed-off-by: Coty Sutherland +Signed-off-by: Adam Stokes +--- + sos/plugins/apache.py | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/sos/plugins/apache.py b/sos/plugins/apache.py +index dc700cb..551b062 100644 +--- a/sos/plugins/apache.py ++++ b/sos/plugins/apache.py +@@ -34,7 +34,8 @@ class RedHatApache(Apache, RedHatPlugin): + + self.add_copy_spec([ + "/etc/httpd/conf/httpd.conf", +- "/etc/httpd/conf.d/*.conf" ++ "/etc/httpd/conf.d/*.conf", ++ "/etc/httpd/conf.modules.d/*.conf" + ]) + + self.add_forbidden_path("/etc/httpd/conf/password.conf") +-- +1.8.3.1 + diff --git a/sos-infiniband-more-diagnostic.patch b/sos-infiniband-more-diagnostic.patch new file mode 100644 index 0000000..7371e67 --- /dev/null +++ b/sos-infiniband-more-diagnostic.patch @@ -0,0 +1,53 @@ +From 8eed8e33d1de2cd56a26fc7cc8a3ee25e8921319 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Tue, 10 Feb 2015 19:24:39 +0000 +Subject: [PATCH] [infiniband] add opensm and infiniband-diags support + +Collect opensm and rdma configuration and logs and output from +the infiniband-diags commands. + +Fixes #492. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/infiniband.py | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/sos/plugins/infiniband.py b/sos/plugins/infiniband.py +index b0437d7..687b8d6 100644 +--- a/sos/plugins/infiniband.py ++++ b/sos/plugins/infiniband.py +@@ -23,20 +23,27 @@ class Infiniband(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin): + + plugin_name = 'infiniband' + profiles = ('hardware',) +- packages = ('libibverbs-utils',) ++ packages = ('libibverbs-utils', 'opensm', 'rdma', 'infiniband-diags') + + def setup(self): + self.add_copy_spec([ + "/etc/ofed/openib.conf", +- "/etc/ofed/opensm.conf" ++ "/etc/ofed/opensm.conf", ++ "/etc/rdma" + ]) + ++ self.add_copy_spec_limit("/var/log/opensm*", ++ sizelimit=self.get_option("log_size")) ++ + self.add_cmd_output([ + "ibv_devices", + "ibv_devinfo", + "ibstat", + "ibstatus", +- "ibhosts" ++ "ibhosts", ++ "iblinkinfo", ++ "sminfo", ++ "perfquery" + ]) + + return +-- +1.8.3.1 + diff --git a/sos-iprconfig-enable-on-ppc64le.patch b/sos-iprconfig-enable-on-ppc64le.patch new file mode 100644 index 0000000..89291fc --- /dev/null +++ b/sos-iprconfig-enable-on-ppc64le.patch @@ -0,0 +1,35 @@ +From f2d9cc519ac549b9e68e1301b67f1e9b789e2fd3 Mon Sep 17 00:00:00 2001 +From: Kamalesh Babulal +Date: Fri, 3 Jul 2015 12:16:25 +0100 +Subject: [PATCH] iprconfig collects information, only if the underlying + platform is 'ppc64'. Modify check_enabled() to regex match on arch(), instead + of exact match of string. + +This enables iprconfig to collect information on ppc64* +platforms. + +Signed-off-by: Kamalesh Babulal +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/iprconfig.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) +--- + sos/plugins/iprconfig.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sos/plugins/iprconfig.py b/sos/plugins/iprconfig.py +index b77c192..687d8d5 100644 +--- a/sos/plugins/iprconfig.py ++++ b/sos/plugins/iprconfig.py +@@ -28,7 +28,7 @@ class IprConfig(Plugin, RedHatPlugin, UbuntuPlugin, DebianPlugin): + + def check_enabled(self): + arch = self.policy().get_arch() +- return arch == "ppc64" and is_executable("iprconfig") ++ return "ppc64" in arch and is_executable("iprconfig") + + def setup(self): + self.add_cmd_output([ +-- +1.8.3.1 + diff --git a/sos-iprconfig-plugin.patch b/sos-iprconfig-plugin.patch new file mode 100644 index 0000000..d294ebf --- /dev/null +++ b/sos-iprconfig-plugin.patch @@ -0,0 +1,135 @@ +From ad464fcc0882f8764e8bbb091a91eeeb4a804ff3 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Mon, 15 Dec 2014 17:30:24 +0000 +Subject: [PATCH] [iprconfig] add plugin for IBM Power RAID adapters + +Capture information which helps in better understanding of +IBM Power RAID storage adapter configuration. Since iprconfig +is specific to power adding the relevant commands in powerpc plugin. + +Signed-off-by: Aruna Balakrishnaiah +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/iprconfig.py | 110 +++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 110 insertions(+) + create mode 100644 sos/plugins/iprconfig.py + +diff --git a/sos/plugins/iprconfig.py b/sos/plugins/iprconfig.py +new file mode 100644 +index 0000000..b77c192 +--- /dev/null ++++ b/sos/plugins/iprconfig.py +@@ -0,0 +1,110 @@ ++# 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 plugin enables collection of logs for Power systems ++ ++import os ++import re ++from sos.plugins import Plugin, RedHatPlugin, UbuntuPlugin, DebianPlugin ++from sos.utilities import is_executable ++ ++ ++class IprConfig(Plugin, RedHatPlugin, UbuntuPlugin, DebianPlugin): ++ """IBM Power RAID storage adapter configuration information ++ """ ++ ++ plugin_name = 'iprconfig' ++ ++ def check_enabled(self): ++ arch = self.policy().get_arch() ++ return arch == "ppc64" and is_executable("iprconfig") ++ ++ def setup(self): ++ self.add_cmd_output([ ++ "iprconfig -c show-config", ++ "iprconfig -c show-alt-config", ++ "iprconfig -c show-arrays", ++ "iprconfig -c show-jbod-disks", ++ "iprconfig -c show-ioas", ++ ]) ++ ++ show_ioas = self.call_ext_prog("iprconfig -c show-ioas") ++ if not show_ioas['status'] == 0: ++ return ++ ++ devices = [] ++ if show_ioas['output']: ++ p = re.compile('sg') ++ for line in show_ioas['output'].splitlines(): ++ temp = line.split(' ') ++ # temp[0] holds the device name ++ if p.search(temp[0]): ++ devices.append(temp[0]) ++ ++ for device in devices: ++ self.add_cmd_output("iprconfig -c show-details %s" % (device,)) ++ ++ # Look for IBM Power RAID enclosures (iprconfig lists them) ++ show_config = self.call_ext_prog("iprconfig -c show-config") ++ if not show_config['status'] == 0: ++ return ++ ++ if not show_config['output']: ++ return ++ ++# iprconfig -c show-config ++# Name PCI/SCSI Location Description Status ++# ------ ------------------------- ------------------------- ----------------- ++# 0005:60:00.0/0: PCI-E SAS RAID Adapter Operational ++# sda 0005:60:00.0/0:0:0:0 Physical Disk Active ++# sdb 0005:60:00.0/0:1:0:0 Physical Disk Active ++# sdc 0005:60:00.0/0:2:0:0 Physical Disk Active ++# sdd 0005:60:00.0/0:3:0:0 Physical Disk Active ++# sde 0005:60:00.0/0:4:0:0 Physical Disk Active ++# sdf 0005:60:00.0/0:5:0:0 Physical Disk Active ++# 0005:60:00.0/0:8:0:0 Enclosure Active ++# 0005:60:00.0/0:8:1:0 Enclosure Active ++ ++ show_alt_config = "iprconfig -c show-alt-config" ++ altconfig = self.call_ext_prog(show_alt_config) ++ if not (altconfig['status'] == 0): ++ return ++ ++ if not altconfig['output']: ++ return ++ ++# iprconfig -c show-alt-config ++# Name Resource Path/Address Vendor Product ID Status ++# ------ -------------------------- -------- ---------------- ----------------- ++# sg9 0: IBM 57C7001SISIOA Operational ++# sg0 0:0:0:0 IBM MBF2300RC Active ++# sg1 0:1:0:0 IBM MBF2300RC Active ++# sg2 0:2:0:0 IBM HUC106030CSS600 Active ++# sg3 0:3:0:0 IBM HUC106030CSS600 Active ++# sg4 0:4:0:0 IBM HUC106030CSS600 Active ++# sg5 0:5:0:0 IBM HUC106030CSS600 Active ++# sg7 0:8:0:0 IBM VSBPD6E4A 3GSAS Active ++# sg8 0:8:1:0 IBM VSBPD6E4B 3GSAS Active ++ ++ for line in show_config['output'].splitlines(): ++ if "Enclosure" in line: ++ temp = re.split('\s+', line) ++ # temp[1] holds the PCI/SCSI location ++ pci, scsi = temp[1].split('/') ++ for line in altconfig['output'].splitlines(): ++ if scsi in line: ++ temp = line.split(' ') ++ # temp[0] holds device name ++ self.add_cmd_output("iprconfig -c " ++ "query-ses-mode %s" % (temp[0],)) +-- +1.8.3.1 + diff --git a/sos-kernel-additional-diagnostic.patch b/sos-kernel-additional-diagnostic.patch new file mode 100644 index 0000000..1acf175 --- /dev/null +++ b/sos-kernel-additional-diagnostic.patch @@ -0,0 +1,276 @@ +From 9c1e646da727817de23c0b46a16885c03c7d4af1 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Tue, 10 Feb 2015 19:34:50 +0000 +Subject: [PATCH] [kernel] collect /sys/firmware/acpi/* + +Collect ACPI firmware tables and state from /sys. + +Related: #490. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/kernel.py | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sos/plugins/kernel.py b/sos/plugins/kernel.py +index 877b2bb..6b93ab7 100644 +--- a/sos/plugins/kernel.py ++++ b/sos/plugins/kernel.py +@@ -49,6 +49,7 @@ class Kernel(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin): + "/sys/module/*/initstate", + "/sys/module/*/refcnt", + "/sys/module/*/taint", ++ "/sys/firmware/acpi/*", + "/proc/kallsyms", + "/proc/buddyinfo", + "/proc/slabinfo", +-- +1.8.3.1 + +From 14686f55bd5bc7169eb06a871ada7bc3461b306b Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Tue, 10 Feb 2015 19:43:08 +0000 +Subject: [PATCH] [memory] add ksm, swap and vmallocinfo data to plugin + +Related: #490. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/memory.py | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/sos/plugins/memory.py b/sos/plugins/memory.py +index 0f20e99..1b27eba 100644 +--- a/sos/plugins/memory.py ++++ b/sos/plugins/memory.py +@@ -27,9 +27,16 @@ class Memory(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin): + "/proc/pci", + "/proc/meminfo", + "/proc/vmstat", ++ "/proc/swaps", + "/proc/slabinfo", +- "/proc/pagetypeinfo"]) ++ "/proc/pagetypeinfo", ++ "/proc/vmallocinfo", ++ "/sys/kernel/mm/ksm" ++ ]) + self.add_cmd_output("free", root_symlink="free") +- self.add_cmd_output("free -m") ++ self.add_cmd_output([ ++ "free -m", ++ "swapon --show" ++ ]) + + # vim: et ts=4 sw=4 +-- +1.8.3.1 + +From 58a6d777d7b5fc4ef72e185ccd916110a73f48d2 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Tue, 10 Feb 2015 19:47:14 +0000 +Subject: [PATCH] [block] collect /proc/diskstats + +Related: #490. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/block.py | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/sos/plugins/block.py b/sos/plugins/block.py +index 8c73ef6..7984f0d 100644 +--- a/sos/plugins/block.py ++++ b/sos/plugins/block.py +@@ -24,8 +24,6 @@ class Block(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin): + profiles = ('storage', 'hardware') + + def setup(self): +- self.add_copy_spec("/proc/partitions") +- + self.add_cmd_output([ + "lsblk", + "blkid -c /dev/null", +@@ -36,7 +34,9 @@ class Block(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin): + # legacy location for non-/run distributions + self.add_copy_spec([ + "/etc/blkid.tab", +- "/run/blkid/blkid.tab" ++ "/run/blkid/blkid.tab", ++ "/proc/partitions", ++ "/proc/diskstats" + ]) + + if os.path.isdir("/sys/block"): +-- +1.8.3.1 + +From 4cc076409f65792c071e4cf027a78c847f7b5ff8 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Tue, 10 Feb 2015 19:48:59 +0000 +Subject: [PATCH] [process] collect /proc/sched_debug + +Related: #490. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/process.py | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sos/plugins/process.py b/sos/plugins/process.py +index ab66322..cae8443 100644 +--- a/sos/plugins/process.py ++++ b/sos/plugins/process.py +@@ -23,6 +23,7 @@ class Process(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin): + profiles = ('system',) + + def setup(self): ++ 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") +-- +1.8.3.1 + +From f3ec78df7060c4ac3cead99775f162a9b5d604f7 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Wed, 11 Feb 2015 20:06:59 +0000 +Subject: [PATCH] [kernel] collect directory listings for module updates + +Related #490. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/kernel.py | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/sos/plugins/kernel.py b/sos/plugins/kernel.py +index 6b93ab7..97300e2 100644 +--- a/sos/plugins/kernel.py ++++ b/sos/plugins/kernel.py +@@ -14,6 +14,7 @@ + + from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin + import os ++import glob + + + class Kernel(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin): +@@ -36,10 +37,21 @@ class Kernel(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin): + 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" ++ "dkms status", ++ "find %s -ls" % " ".join(extra_mod_paths) + ]) + + self.add_copy_spec([ +-- +1.8.3.1 + +From 895803a4c7d014b231cfe9804bd1c04fe37b5f5e Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Wed, 11 Feb 2015 20:15:37 +0000 +Subject: [PATCH] [mpt] add plugin + +Add a plugin to collect LSI Message Passing Technology driver +status from /proc. + +Related: #490. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/mpt.py | 30 ++++++++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) + create mode 100644 sos/plugins/mpt.py + +diff --git a/sos/plugins/mpt.py b/sos/plugins/mpt.py +new file mode 100644 +index 0000000..bb158cc +--- /dev/null ++++ b/sos/plugins/mpt.py +@@ -0,0 +1,30 @@ ++# 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: et ts=4 sw=4 +-- +1.8.3.1 + +From fc4e2be53eeeaa9ab0d4d089335bbeb007c1817e Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Thu, 27 Aug 2015 18:07:46 +0100 +Subject: [PATCH] [memory] collect swapon --show output in bytes + +Default is human readable: + +$ swapon --show +NAME TYPE SIZE USED PRIO +/dev/dm-0 partition 1.5G 0B -1 + +Should be: + +$ swapon --show --bytes +NAME TYPE SIZE USED PRIO +/dev/dm-0 partition 1610608640 0 -1 + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/memory.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sos/plugins/memory.py b/sos/plugins/memory.py +index 4c41896..710f73f 100644 +--- a/sos/plugins/memory.py ++++ b/sos/plugins/memory.py +@@ -36,7 +36,7 @@ class Memory(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin): + self.add_cmd_output("free", root_symlink="free") + self.add_cmd_output([ + "free -m", +- "swapon --show" ++ "swapon --bytes --show" + ]) + + # vim: et ts=4 sw=4 +-- +1.8.3.1 + diff --git a/sos-kimchid-plugin.patch b/sos-kimchid-plugin.patch new file mode 100644 index 0000000..748e8f4 --- /dev/null +++ b/sos-kimchid-plugin.patch @@ -0,0 +1,99 @@ +From 3aabd18b2666dbbeb86871ac4b9f025e468d5818 Mon Sep 17 00:00:00 2001 +From: Christy Perez +Date: Tue, 16 Dec 2014 12:46:27 +0000 +Subject: [PATCH] [kimchi] add new plugin + +This plugin gathers kimchi logs and configuration files. + +Kimchi is an HTML5-based virtualization-management platform +For more information, please visit: +https://github.com/kimchi-project/kimchi/wiki + +Signed-off-by: Christy Perez +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/kimchi.py | 40 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 40 insertions(+) + create mode 100644 sos/plugins/kimchi.py + +diff --git a/sos/plugins/kimchi.py b/sos/plugins/kimchi.py +new file mode 100644 +index 0000000..613b2c9 +--- /dev/null ++++ b/sos/plugins/kimchi.py +@@ -0,0 +1,40 @@ ++# Copyright IBM, Corp. 2014, Christy Perez ++ ++# 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 Kimchi(Plugin, RedHatPlugin, UbuntuPlugin, DebianPlugin): ++ """kimchi-related information ++ """ ++ ++ plugin_name = 'kimchi' ++ packages = ('kimchi',) ++ ++ def setup(self): ++ log_limit = self.get_option('log_size') ++ if not self.get_option('all_logs'): ++ self.add_copy_spec_limit('/var/log/kimchi/*.log', ++ sizelimit=log_limit) ++ self.add_copy_spec_limit('/etc/kimchi/kimchi*', ++ sizelimit=log_limit) ++ self.add_copy_spec_limit('/etc/kimchi/distros.d/*.json', ++ sizelimit=log_limit) ++ else: ++ self.add_copy_spec('/var/log/kimchi/') ++ self.add_copy_spec('/etc/kimchi/') ++ ++# vim: expandtab tabstop=4 shiftwidth=4 +-- +1.8.3.1 + +From cb9805d129827178df5b32fc681f629d4f40ac6e Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Tue, 10 Feb 2015 19:09:26 +0000 +Subject: [PATCH] [kimchi] fix collection of /etc/kimchi + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/kimchi.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sos/plugins/kimchi.py b/sos/plugins/kimchi.py +index 613b2c9..efb469e 100644 +--- a/sos/plugins/kimchi.py ++++ b/sos/plugins/kimchi.py +@@ -26,6 +26,7 @@ class Kimchi(Plugin, RedHatPlugin, UbuntuPlugin, DebianPlugin): + + def setup(self): + log_limit = self.get_option('log_size') ++ self.add_copy_spec('/etc/kimchi/') + if not self.get_option('all_logs'): + self.add_copy_spec_limit('/var/log/kimchi/*.log', + sizelimit=log_limit) +@@ -35,6 +36,5 @@ class Kimchi(Plugin, RedHatPlugin, UbuntuPlugin, DebianPlugin): + sizelimit=log_limit) + else: + self.add_copy_spec('/var/log/kimchi/') +- self.add_copy_spec('/etc/kimchi/') + + # vim: expandtab tabstop=4 shiftwidth=4 +-- +1.8.3.1 + diff --git a/sos-logs-plugin-traceback.patch b/sos-logs-plugin-traceback.patch new file mode 100644 index 0000000..c6d2360 --- /dev/null +++ b/sos-logs-plugin-traceback.patch @@ -0,0 +1,25 @@ +From b3faad3f82ee1f735e2221bb2f39b8b8aeaf0e86 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Mon, 3 Aug 2015 16:39:53 +0100 +Subject: [PATCH] [logs] fix reference to missing 'rsyslog_conf' variable + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/logs.py | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sos/plugins/logs.py b/sos/plugins/logs.py +index 7957898..70ef537 100644 +--- a/sos/plugins/logs.py ++++ b/sos/plugins/logs.py +@@ -42,6 +42,7 @@ class Logs(Plugin): + 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: +-- +1.8.3.1 + diff --git a/sos-mariadb-mysql-add-log.patch b/sos-mariadb-mysql-add-log.patch new file mode 100644 index 0000000..6d57ebe --- /dev/null +++ b/sos-mariadb-mysql-add-log.patch @@ -0,0 +1,37 @@ +From f8ab86cbd2302812cd9160bec4478cb4f84e1442 Mon Sep 17 00:00:00 2001 +From: Shane Bradley +Date: Mon, 27 Apr 2015 10:28:34 -0400 +Subject: [PATCH] [mysql] Collect log file + +When MariaDB is run under Pacemaker an OCF resource agent is used +to start and stop the database. This configuration also overrides +the log paths used for the database. In particular the mysqld.log +is present at '/var/log/mysqld.log'. + +Collect both paths as we do not currently detect whether we are +running with an OCF agent or stand-alone. + +Fixes: #554 + +Signed-off-by: Shane Bradley +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/mysql.py | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sos/plugins/mysql.py b/sos/plugins/mysql.py +index 8dba204..aa8e9b9 100644 +--- a/sos/plugins/mysql.py ++++ b/sos/plugins/mysql.py +@@ -37,6 +37,8 @@ class Mysql(Plugin): + + 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", + ]) +-- +1.8.3.1 + diff --git a/sos-mysql-fix-command-line-dbpass-handling.patch b/sos-mysql-fix-command-line-dbpass-handling.patch new file mode 100644 index 0000000..1cfa94e --- /dev/null +++ b/sos-mysql-fix-command-line-dbpass-handling.patch @@ -0,0 +1,39 @@ +From db9ac3fb615b731be87b4116a8939105bf5ced56 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Tue, 23 Dec 2014 14:40:50 +0000 +Subject: [PATCH] [mysql] fix command-line dbpass handling + +The logic for chosing between a command-line and environment +variable passed password in the MySQL plugin was incorrect. This +prevents a database dump from being collected when a password is +given on the command line. + +Altough use of the command line to pass authentication tokens +is discouraged we should ensure the case works. + +Fixes #456. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/mysql.py | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/sos/plugins/mysql.py b/sos/plugins/mysql.py +index d148472..edab6d0 100644 +--- a/sos/plugins/mysql.py ++++ b/sos/plugins/mysql.py +@@ -45,9 +45,9 @@ class Mysql(Plugin): + if self.get_option("dbdump"): + dbuser = self.get_option("dbuser") + dbpass = self.get_option("dbpass") +- if dbpass is False and 'MYSQL_PWD' in os.environ: ++ if 'MYSQL_PWD' in os.environ: + dbpass = os.environ['MYSQL_PWD'] +- else: ++ if not dbpass or dbpass is False: + # no MySQL password + return + os.environ['MYSQL_PWD'] = dbpass +-- +1.9.3 + diff --git a/sos-mysql-improve-dbuser-dbpass-handling.patch b/sos-mysql-improve-dbuser-dbpass-handling.patch new file mode 100644 index 0000000..e6f2d49 --- /dev/null +++ b/sos-mysql-improve-dbuser-dbpass-handling.patch @@ -0,0 +1,80 @@ +From 7c12e6c994b3320ef57a13e06f5c445b6bca7935 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Thu, 22 Jan 2015 15:37:15 +0000 +Subject: [PATCH] [mysql] improve handling of dbuser, dbpass and MYSQL_PWD + +Make sure that the mysql plugin behaves correctly when given +different combinations of values for dbuser, dbpass and MYSQL_PWD. + +* If dbdump is set then either dbpass or MYSQL_PWD must be set +* Warn if dbdump is set and dbuser or dbpass is True/False/null + (indicates either 'sosreport -a' or '-k mysql.dbpass') + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/mysql.py | 24 ++++++++++++++++++++---- + 1 file changed, 20 insertions(+), 4 deletions(-) + +diff --git a/sos/plugins/mysql.py b/sos/plugins/mysql.py +index dd899a3..8dba204 100644 +--- a/sos/plugins/mysql.py ++++ b/sos/plugins/mysql.py +@@ -24,35 +24,51 @@ class Mysql(Plugin): + 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", "", False), ++ ("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, + "/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 isinstance(dbuser, bool) or isinstance(dbpass, bool): +- # sosreport -a +- return ++ + 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 +-- +1.9.3 + diff --git a/sos-mysql-test-for-boolean-values.patch b/sos-mysql-test-for-boolean-values.patch new file mode 100644 index 0000000..8eecd34 --- /dev/null +++ b/sos-mysql-test-for-boolean-values.patch @@ -0,0 +1,44 @@ +From 05466cd6d9d70321fc7a0097334ef36af8dfeb43 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Tue, 20 Jan 2015 16:16:17 +0000 +Subject: [PATCH] [mysql] test for boolean values in user and password options + +If sosreport is run with '-a' all options will be set to boolean +True. This causes an exception if an attempt is made to set an +environment variable to the option value: + + Traceback (most recent call last): + File "/usr/sbin/sosreport", line 25, in + main(sys.argv[1:]) + File "/usr/lib/python2.7/site-packages/sos/sosreport.py", line 1435, in main + sos.execute() + TypeError: must be string, not bool + + > /usr/lib64/python2.7/os.py(471)__setitem__() + -> putenv(key, item) + +Test both values with isinstance(val, bool) and do not attempt to +collect a database dump if either is a boolean. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/mysql.py | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/sos/plugins/mysql.py b/sos/plugins/mysql.py +index edab6d0..dd899a3 100644 +--- a/sos/plugins/mysql.py ++++ b/sos/plugins/mysql.py +@@ -45,6 +45,9 @@ class Mysql(Plugin): + if self.get_option("dbdump"): + dbuser = self.get_option("dbuser") + dbpass = self.get_option("dbpass") ++ if isinstance(dbuser, bool) or isinstance(dbpass, bool): ++ # sosreport -a ++ return + if 'MYSQL_PWD' in os.environ: + dbpass = os.environ['MYSQL_PWD'] + if not dbpass or dbpass is False: +-- +1.9.3 + diff --git a/sos-navicli-catch-unreadable-stdin.patch b/sos-navicli-catch-unreadable-stdin.patch new file mode 100644 index 0000000..44c2667 --- /dev/null +++ b/sos-navicli-catch-unreadable-stdin.patch @@ -0,0 +1,42 @@ +From 465746d768ce69684eee57eaa3509d9ae898fee2 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Wed, 17 Dec 2014 12:39:05 +0000 +Subject: [PATCH] [navicli] catch exception if input is unreadable + +CLARiiON SP IP Address or [Enter] to exit: Traceback (most recent call last): + File "/usr/sbin/sosreport", line 25, in + main(sys.argv[1:]) + File "/usr/lib/python2.7/site-packages/sos/sosreport.py", line 1408, in main + sos.execute() + File "/usr/lib/python2.7/site-packages/sos/sosreport.py", line 1387, in execute + self.setup() + File "/usr/lib/python2.7/site-packages/sos/sosreport.py", line 1117, in setup + plug.setup() + File "/usr/lib/python2.7/site-packages/sos/plugins/navicli.py", line 72, in setup + ans = input("CLARiiON SP IP Address or [Enter] to exit: ") +EOFError: EOF when reading a line + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/navicli.py | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/sos/plugins/navicli.py b/sos/plugins/navicli.py +index 5175f89..3ee7d50 100644 +--- a/sos/plugins/navicli.py ++++ b/sos/plugins/navicli.py +@@ -69,7 +69,10 @@ class Navicli(Plugin, RedHatPlugin): + CLARiiON_IP_address_list = [] + CLARiiON_IP_loop = "stay_in" + while CLARiiON_IP_loop == "stay_in": +- ans = input("CLARiiON SP IP Address or [Enter] to exit: ") ++ 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: +-- +1.9.3 + diff --git a/sos-network-more-diagnostic.patch b/sos-network-more-diagnostic.patch new file mode 100644 index 0000000..80b9754 --- /dev/null +++ b/sos-network-more-diagnostic.patch @@ -0,0 +1,57 @@ +From b61a927bade2f183e7cf9404b11a93570fe8895b Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Tue, 10 Feb 2015 19:30:05 +0000 +Subject: [PATCH] [networking] additional ip, firewall and traffic shaping + commands + +Collect tc qdisc output, ipv4/6 routing policy, NOARP arp cache, +iptables with --exact counters, and iproute2 configuration. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/networking.py | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/sos/plugins/networking.py b/sos/plugins/networking.py +index 8dfc0e6..9f6ece0 100644 +--- a/sos/plugins/networking.py ++++ b/sos/plugins/networking.py +@@ -82,7 +82,8 @@ class Networking(Plugin): + "/etc/NetworkManager/NetworkManager.conf", + "/etc/NetworkManager/system-connections", + "/etc/dnsmasq*", +- "/sys/class/net/*/flags" ++ "/sys/class/net/*/flags", ++ "/etc/iproute2" + ]) + self.add_forbidden_path("/proc/net/rpc/use-gss-proxy") + self.add_forbidden_path("/proc/net/rpc/*/channel") +@@ -98,19 +99,24 @@ class Networking(Plugin): + "netstat -agn", + "ip route show table all", + "ip -6 route show table all", ++ "ip -4 rule", ++ "ip -6 rule", + "ip link", + "ip address", + "ifenslave -a", + "ip mroute show", + "ip maddr show", + "ip neigh show", ++ "ip neigh show nud noarp", + "ip netns", + "nmcli general status", + "nmcli connection show", + "nmcli connection show active", + "nmcli device status", + "nmcli device show", +- "biosdevname -d" ++ "biosdevname -d", ++ "tc -s qdisc show", ++ "iptables -vnxL" + ]) + ip_link_result = self.call_ext_prog("ip -o link") + if ip_link_result['status'] == 0: +-- +1.8.3.1 + diff --git a/sos-networking-ip-addr.patch b/sos-networking-ip-addr.patch new file mode 100644 index 0000000..c2cd2bf --- /dev/null +++ b/sos-networking-ip-addr.patch @@ -0,0 +1,28 @@ +From 79d90ff649f89f784bdf41769f2326faa11cb7b0 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Tue, 17 Mar 2015 13:50:37 +0000 +Subject: [PATCH] [networking] re-add 'ip addr' with a root symlink + +Commit e320ca8 accidentally deleted collection of "ip -o addr" +and the root "ip_addr" symlink: put it back. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/networking.py | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sos/plugins/networking.py b/sos/plugins/networking.py +index ae6cb1b..ae5ea71 100644 +--- a/sos/plugins/networking.py ++++ b/sos/plugins/networking.py +@@ -89,6 +89,7 @@ class Networking(Plugin): + self.add_forbidden_path("/proc/net/rpc/*/channel") + self.add_forbidden_path("/proc/net/rpc/*/flush") + ++ self.add_cmd_output("ip -o addr", root_symlink = "ip_addr") + self.add_cmd_output("route -n", root_symlink="route") + self.collect_iptable("filter") + self.collect_iptable("nat") +-- +1.8.3.1 + diff --git a/sos-obtain-mysql-password-from-env.patch b/sos-obtain-mysql-password-from-env.patch new file mode 100644 index 0000000..fcd3980 --- /dev/null +++ b/sos-obtain-mysql-password-from-env.patch @@ -0,0 +1,89 @@ +From 3d4cf0365d520be81abfe3435fa9a8a56a933961 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Mon, 20 Oct 2014 09:31:32 +0100 +Subject: [PATCH 1/2] [mysql] obtain dbpass from the environment + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/mysql.py | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/sos/plugins/mysql.py b/sos/plugins/mysql.py +index 8bc6e72..1203f5c 100644 +--- a/sos/plugins/mysql.py ++++ b/sos/plugins/mysql.py +@@ -13,7 +13,7 @@ + # 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 +@@ -25,7 +25,7 @@ class Mysql(Plugin): + + option_list = [ + ("dbuser", "username for database dumps", "", "mysql"), +- ("dbpass", "password for database dumps", "", ""), ++ ("dbpass", "password for database dumps", "", False), + ("dbdump", "collect a database dump", "", False) + ] + +@@ -44,7 +44,14 @@ class Mysql(Plugin): + if self.get_option("dbdump"): + dbuser = self.get_option("dbuser") + dbpass = self.get_option("dbpass") +- opts = "--user=%s --password=%s --all-databases" % (dbuser, dbpass) ++ if dbpass == False and 'MYSQL_PWD' in os.environ: ++ dbpass = os.environ['MYSQL_PWD'] ++ else: ++ # no MySQL password ++ return ++ 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) + +-- +1.9.3 + + +From 6ce502113f550c027424fa477edc091283c32e50 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Mon, 20 Oct 2014 14:33:57 +0100 +Subject: [PATCH 2/2] [mysql] fix pep8 violations + +The previous commit had a couple of pep8 errors that were fixed +in the working tree but not added to the commit; fix them. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/mysql.py | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/sos/plugins/mysql.py b/sos/plugins/mysql.py +index 1203f5c..d148472 100644 +--- a/sos/plugins/mysql.py ++++ b/sos/plugins/mysql.py +@@ -15,6 +15,7 @@ + from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin + import os + ++ + class Mysql(Plugin): + """MySQL and MariaDB RDBMS + """ +@@ -44,7 +45,7 @@ class Mysql(Plugin): + if self.get_option("dbdump"): + dbuser = self.get_option("dbuser") + dbpass = self.get_option("dbpass") +- if dbpass == False and 'MYSQL_PWD' in os.environ: ++ if dbpass is False and 'MYSQL_PWD' in os.environ: + dbpass = os.environ['MYSQL_PWD'] + else: + # no MySQL password +-- +1.9.3 + diff --git a/sos-openstack-neutron-to-collect-neutron-folders.patch b/sos-openstack-neutron-to-collect-neutron-folders.patch new file mode 100644 index 0000000..f4beb63 --- /dev/null +++ b/sos-openstack-neutron-to-collect-neutron-folders.patch @@ -0,0 +1,40 @@ +From 3f8c4b658c5d702bde59bdd98cb114ea0064eae9 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Thu, 9 Oct 2014 17:07:38 +0100 +Subject: [PATCH] [openstack_neutron] fix legacy component detection test + +Currently the Neutron plugin will assume it's running on a Neutron +(rather than a legacy Quantum) installation if: + + - '/etc/neutron' exists AND the user specifies quantum=True + +Otherwise it's assumed to be a Quantum install. This is clearly +broken; the sense of the 'openstack_neutron.quantum' part of the +test should be inverted. + +Fixes #420. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/openstack_neutron.py | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/sos/plugins/openstack_neutron.py b/sos/plugins/openstack_neutron.py +index dba192e..d37430e 100644 +--- a/sos/plugins/openstack_neutron.py ++++ b/sos/plugins/openstack_neutron.py +@@ -40,10 +40,7 @@ class Neutron(Plugin): + component_name = "neutron" + + def setup(self): +- if os.path.exists("/etc/neutron/") and \ +- self.get_option("quantum", False): +- self.component_name = self.plugin_name +- else: ++ if not os.path.exists("/etc/neutron/") or self.get_option("quantum"): + self.component_name = "quantum" + + self.add_copy_spec([ +-- +1.8.3.1 + diff --git a/sos-openstack-obfuscate-passwords-secrets.patch b/sos-openstack-obfuscate-passwords-secrets.patch new file mode 100644 index 0000000..46f171f --- /dev/null +++ b/sos-openstack-obfuscate-passwords-secrets.patch @@ -0,0 +1,357 @@ +From 02ef6e2ba8d1a8fe4468aaa8be0ae88f8c74646a Mon Sep 17 00:00:00 2001 +From: Lee Yarwood +Date: Wed, 15 Jul 2015 15:42:50 +0100 +Subject: [PATCH] [openstack] Ensure openstack passwords and secrets are + obfuscated. + +- Add a postproc method to ceilometer, cinder, glance, hoirzon and swift. +- Add missing keys to the remaining plugins. +- Modify the regular expression used by all plugins to ignore commented + out keys. +- Modify all plugins to use do_path_regex_sub() to apply regex to all + collected configuration files. + +Resolves: #574 + +Signed-off-by: Lee Yarwood +--- + sos/plugins/openstack_ceilometer.py | 12 ++++++++++++ + sos/plugins/openstack_cinder.py | 17 +++++++++++++++++ + sos/plugins/openstack_glance.py | 10 ++++++++++ + sos/plugins/openstack_heat.py | 9 +++++++++ + sos/plugins/openstack_horizon.py | 9 +++++++++ + sos/plugins/openstack_keystone.py | 23 ++++++++--------------- + sos/plugins/openstack_neutron.py | 17 ++++++++--------- + sos/plugins/openstack_nova.py | 10 +++++----- + sos/plugins/openstack_sahara.py | 11 +++++------ + sos/plugins/openstack_swift.py | 11 +++++++++++ + sos/plugins/openstack_trove.py | 19 ++++++------------- + 11 files changed, 100 insertions(+), 48 deletions(-) + +diff --git a/sos/plugins/openstack_ceilometer.py b/sos/plugins/openstack_ceilometer.py +index 7c11057..44a733b 100644 +--- a/sos/plugins/openstack_ceilometer.py ++++ b/sos/plugins/openstack_ceilometer.py +@@ -35,6 +35,18 @@ class OpenStackCeilometer(Plugin): + "/var/log/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 DebianOpenStackCeilometer(OpenStackCeilometer, DebianPlugin, + UbuntuPlugin): +diff --git a/sos/plugins/openstack_cinder.py b/sos/plugins/openstack_cinder.py +index 8588f6c..2f22b5a 100644 +--- a/sos/plugins/openstack_cinder.py ++++ b/sos/plugins/openstack_cinder.py +@@ -42,6 +42,23 @@ class OpenStackCinder(Plugin): + if self.get_option("log"): + self.add_copy_spec(["/var/log/cinder/"]) + ++ def postproc(self): ++ protect_keys = [ ++ "admin_password", "backup_tsm_password", "chap_password", ++ "nas_password", "cisco_fc_fabric_password", "coraid_password", ++ "eqlx_chap_password", "fc_fabric_password", ++ "hitachi_auth_password", "hitachi_horcm_password", ++ "hp3par_password", "hplefthand_password", "memcache_secret_key", ++ "netapp_password", "netapp_sa_password", "nexenta_password", ++ "password", "qpid_password", "rabbit_password", "san_password", ++ "ssl_key_password", "vmware_host_password", "zadara_password", ++ "zfssa_initiator_password", "connection", "zfssa_target_password", ++ "os_privileged_user_password", "hmac_keys" ++ ] ++ ++ regexp = r"((?m)^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys) ++ self.do_path_regex_sub("/etc/cinder/*", regexp, r"\1*********") ++ + + class DebianOpenStackCinder(OpenStackCinder, DebianPlugin, UbuntuPlugin): + +diff --git a/sos/plugins/openstack_glance.py b/sos/plugins/openstack_glance.py +index 35c406a..33e69a9 100644 +--- a/sos/plugins/openstack_glance.py ++++ b/sos/plugins/openstack_glance.py +@@ -38,6 +38,16 @@ class OpenStackGlance(plugins.Plugin): + "/var/log/glance/" + ]) + ++ def postproc(self): ++ protect_keys = [ ++ "admin_password", "password", "qpid_password", "rabbit_password", ++ "s3_store_secret_key", "ssl_key_password", "connection", ++ "vmware_server_password" ++ ] ++ ++ regexp = r"((?m)^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys) ++ self.do_path_regex_sub("/etc/glance/*", regexp, r"\1*********") ++ + + class DebianOpenStackGlance(OpenStackGlance, + plugins.DebianPlugin, + +diff --git a/sos/plugins/openstack_heat.py b/sos/plugins/openstack_heat.py +index 70185db..b60285a 100644 +--- a/sos/plugins/openstack_heat.py ++++ b/sos/plugins/openstack_heat.py +@@ -36,6 +36,15 @@ class OpenStackHeat(Plugin): + "/var/log/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 DebianOpenStack(OpenStackHeat, + plugins.DebianPlugin, + +diff --git a/sos/plugins/openstack_horizon.py b/sos/plugins/openstack_horizon.py +index 4c93cd9..5449ce9 100644 +--- a/sos/plugins/openstack_horizon.py ++++ b/sos/plugins/openstack_horizon.py +@@ -33,6 +33,15 @@ class OpenStackHorizon(Plugin): + if self.get_option("log"): + self.add_copy_spec("/var/log/horizon/") + ++ 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/*", ++ regexp, r"\1*********") ++ + + class DebianOpenStackHorizon(OpenStackHorizon, DebianPlugin): + +diff --git a/sos/plugins/openstack_keystone.py b/sos/plugins/openstack_keystone.py +index 7d93d88..bff9ef6 100644 +--- a/sos/plugins/openstack_keystone.py ++++ b/sos/plugins/openstack_keystone.py +@@ -38,21 +38,14 @@ class OpenStackKeystone(Plugin): + self.add_copy_spec("/var/log/keystone/") + + def postproc(self): +- self.do_file_sub('/etc/keystone/keystone.conf', +- r"(?m)^(admin_password.*=)(.*)", +- r"\1 ******") +- self.do_file_sub('/etc/keystone/keystone.conf', +- r"(?m)^(admin_token.*=)(.*)", +- r"\1 ******") +- self.do_file_sub('/etc/keystone/keystone.conf', +- r"(?m)^(connection.*=.*mysql://)(.*)(:)(.*)(@)(.*)", +- r"\1\2:******@\6") +- self.do_file_sub('/etc/keystone/keystone.conf', +- r"(?m)^(password.*=)(.*)", +- r"\1 ******") +- self.do_file_sub('/etc/keystone/keystone.conf', +- r"(?m)^(ca_password.*=)(.*)", +- r"\1 ******") ++ protect_keys = [ ++ "password", "qpid_password", "rabbit_password", "ssl_key_password", ++ "ldap_dns_password", "neutron_admin_password", "host_password", ++ "connection", "admin_password", "admin_token", "ca_password" ++ ] ++ ++ regexp = r"((?m)^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys) ++ self.do_path_regex_sub("/etc/keystone/*", regexp, r"\1*********") + + + class DebianOpenStackKeystone(OpenStackKeystone, DebianPlugin, UbuntuPlugin): +diff --git a/sos/plugins/openstack_neutron.py b/sos/plugins/openstack_neutron.py +index ab895c8..91ee9f5 100644 +--- a/sos/plugins/openstack_neutron.py ++++ b/sos/plugins/openstack_neutron.py +@@ -14,7 +14,6 @@ + # along with this program; if not, write to the Free Software + # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +-import glob + import os + import re + +@@ -55,16 +54,16 @@ class Neutron(Plugin): + protect_keys = [ + "rabbit_password", "qpid_password", "nova_admin_password", + "xenapi_connection_password", "password", "connection", +- "admin_password", "metadata_proxy_shared_secret", "qpid_password", +- "eapi_password", "crd_password", "primary_l3_host_password", +- "serverauth", "ucsm_password", "ha_vrrp_auth_password", +- "ssl_key_password", "nsx_password", "vcenter_password", +- "edge_appliance_password", "tenant_admin_password", "apic_password" ++ "admin_password", "metadata_proxy_shared_secret", "eapi_password", ++ "crd_password", "primary_l3_host_password", "serverauth", ++ "ucsm_password", "ha_vrrp_auth_password", "ssl_key_password", ++ "nsx_password", "vcenter_password", "edge_appliance_password", ++ "tenant_admin_password", "apic_password" + ] +- regexp = r"((?m)^\s*#*(%s)\s*=\s*)(.*)" % "|".join(protect_keys) ++ regexp = r"((?m)^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys) + +- for config_file in glob.glob("/etc/%s/*" % self.component_name): +- self.do_file_sub(config_file, regexp, r"\1*********") ++ self.do_path_regex_sub("/etc/%s/*" % self.component_name, ++ regexp, r"\1*********") + + def netns_dumps(self): + # It would've been beautiful if we could get parts of the networking +diff --git a/sos/plugins/openstack_nova.py b/sos/plugins/openstack_nova.py +index 20fb3a3..e226dac 100644 +--- a/sos/plugins/openstack_nova.py ++++ b/sos/plugins/openstack_nova.py +@@ -66,13 +66,13 @@ class OpenStackNova(Plugin): + "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" ++ "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) +- +- for conf_file in ["/etc/nova/nova.conf", "/etc/nova/api-paste.ini"]: +- self.do_file_sub(conf_file, regexp, r"\1*********") ++ regexp = r"((?m)^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys) ++ self.do_path_regex_sub("/etc/nova/*", regexp, r"\1*********") + + + class DebianOpenStackNova(OpenStackNova, DebianPlugin, UbuntuPlugin): +diff --git a/sos/plugins/openstack_sahara.py b/sos/plugins/openstack_sahara.py +index 9d971ba..18e56d7 100644 +--- a/sos/plugins/openstack_sahara.py ++++ b/sos/plugins/openstack_sahara.py +@@ -33,14 +33,13 @@ class OpenStackSahara(Plugin): + + def postproc(self): + protect_keys = [ +- 'memcache_secret_key', 'qpid_password', 'rabbit_password', +- 'admin_password', 'password', 'ssl_key_password', +- 'admin_token', 'connection' ++ "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_file_sub('/etc/sahara/sahara.conf', regexp, r"\1*********") ++ regexp = r"((?m)^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys) ++ self.do_path_regex_sub("/etc/sahara/*", regexp, r"\1*********") + + + class DebianOpenStackSahara(OpenStackSahara, DebianPlugin, UbuntuPlugin): +diff --git a/sos/plugins/openstack_swift.py b/sos/plugins/openstack_swift.py +index f0f94bb..f337331 100644 +--- a/sos/plugins/openstack_swift.py ++++ b/sos/plugins/openstack_swift.py +@@ -33,6 +33,17 @@ class OpenStackSwift(Plugin): + # Swift + self.add_copy_spec("/etc/swift/") + ++ 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" ++ ] ++ ++ regexp = r"((?m)^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys) ++ self.do_path_regex_sub("/etc/swift/*.conf*", regexp, r"\1*********") ++ + + class DebianOpenStackSwift(OpenStackSwift, DebianPlugin, UbuntuPlugin): + +diff --git a/sos/plugins/openstack_trove.py b/sos/plugins/openstack_trove.py +index 3b87506..566ae42 100644 +--- a/sos/plugins/openstack_trove.py ++++ b/sos/plugins/openstack_trove.py +@@ -14,6 +14,7 @@ + # 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 + + +@@ -34,21 +35,13 @@ class OpenStackTrove(Plugin): + def postproc(self): + + protect_keys = [ +- "dns_passkey", "nova_proxy_admin_pass", "rabbit_password", +- "qpid_password", "connection", "sql_connection", "admin_password" +- ] +- +- conf_list = [ +- '/etc/trove/trove.conf', +- '/etc/trove/trove-conductor.conf', +- '/etc/trove/trove-guestmanager.conf', +- '/etc/trove/trove-taskmanager.conf' ++ "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) +- +- for conf in conf_list: +- self.do_file_sub(conf, regexp, r"\1*********") ++ regexp = r"((?m)^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys) ++ self.do_path_regex_sub("/etc/trove/*", regexp, r"\1*********") + + + class DebianOpenStackTrove(OpenStackTrove, DebianPlugin, UbuntuPlugin): +-- +1.8.3.1 + +From 08ba22aebb066de389cffed414a725e61a6b86d7 Mon Sep 17 00:00:00 2001 +From: Pavel Moravec +Date: Mon, 7 Sep 2015 09:54:17 +0200 +Subject: [PATCH] [openstack_neutron] obfuscate server_auth in restproxy.ini + +server_auth secrets in /etc/neutron/plugins/ml2/restproxy.ini need to be +obfuscated. + +Resolves: #639 + +Signed-off-by: Pavel Moravec +--- + sos/plugins/openstack_neutron.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sos/plugins/openstack_neutron.py b/sos/plugins/openstack_neutron.py +index 91ee9f5..fc494d2 100644 +--- a/sos/plugins/openstack_neutron.py ++++ b/sos/plugins/openstack_neutron.py +@@ -58,7 +58,7 @@ class Neutron(Plugin): + "crd_password", "primary_l3_host_password", "serverauth", + "ucsm_password", "ha_vrrp_auth_password", "ssl_key_password", + "nsx_password", "vcenter_password", "edge_appliance_password", +- "tenant_admin_password", "apic_password" ++ "tenant_admin_password", "apic_password", "server_auth" + ] + regexp = r"((?m)^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys) + +-- +1.8.3.1 + diff --git a/sos-openstack-sahara-plugin.patch b/sos-openstack-sahara-plugin.patch new file mode 100644 index 0000000..23d0eb9 --- /dev/null +++ b/sos-openstack-sahara-plugin.patch @@ -0,0 +1,88 @@ +From f1a7aea0f45485cbe12e95f38c6b0dc6ad12dd58 Mon Sep 17 00:00:00 2001 +From: Poornima +Date: Thu, 9 Apr 2015 18:47:58 +0530 +Subject: [PATCH] [openstack_sahara] add new plugin + +Capture configuration and log data for the OpenStack Sahara project +(formerly Savanna). Sahara is a tool to simplify the deployment of +data-intensive applications in OpenStack environments. + +Signed-off-by: Poornima M. Kshirsagar pkshiras@redhat.com +Signed-off-by: Bryn M. Reeves bmr@redhat.com +--- + sos/plugins/openstack_sahara.py | 63 +++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 63 insertions(+) + create mode 100644 sos/plugins/openstack_sahara.py + +diff --git a/sos/plugins/openstack_sahara.py b/sos/plugins/openstack_sahara.py +new file mode 100644 +index 0000000..f0b95e4 +--- /dev/null ++++ b/sos/plugins/openstack_sahara.py +@@ -0,0 +1,63 @@ ++# 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',) ++ ++ option_list = [("log", "gathers openstack sahara logs", "slow", True)] ++ ++ def setup(self): ++ self.add_copy_spec("/etc/sahara/") ++ self.add_cmd_output("journalctl -u openstack-sahara-all") ++ ++ if self.get_option("log"): ++ self.add_copy_spec("/var/log/sahara/") ++ ++ ++class DebianOpenStackSahara(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(DebianOpenStackSahara, self).setup() ++ ++ ++class RedHatOpenStackSahara(OpenStackSahara, RedHatPlugin): ++ """OpenStack sahara related information for Red Hat distributions.""" ++ ++ packages = ( ++ 'openstack-sahara', ++ 'python-saharaclient' ++ ) ++ ++ def setup(self): ++ super(RedHatOpenStackSahara, self).setup() ++ self.add_copy_spec("/etc/sudoers.d/sahara") ++ ++ ++# vim: et ts=4 sw=4 +-- +1.8.3.1 + diff --git a/sos-openstack_neutron-obfuscate-passwords.patch b/sos-openstack_neutron-obfuscate-passwords.patch new file mode 100644 index 0000000..add6bff --- /dev/null +++ b/sos-openstack_neutron-obfuscate-passwords.patch @@ -0,0 +1,72 @@ +From 5917dbd8f38bab29de9e40d1135b0e9e85cb91bc Mon Sep 17 00:00:00 2001 +From: Lee Yarwood +Date: Tue, 7 Jul 2015 14:54:49 +0100 +Subject: [PATCH] [openstack_neutron] Obscure passwords and secrets + +The following passwords and secrets are now obscured : + + - rabbit_password + - qpid_password + - nova_admin_password + - xenapi_connection_password + - password + - connection + - admin_password + - metadata_proxy_shared_secret + - qpid_password + - eapi_password + - crd_password + - primary_l3_host_password + - serverauth + - ucsm_password + - ha_vrrp_auth_password + - ssl_key_password + - vcenter_password + - edge_appliance_password + - tenant_admin_password + - apic_password + +Fixes #594 + +Signed-off-by: Lee Yarwood +--- + sos/plugins/openstack_neutron.py | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/sos/plugins/openstack_neutron.py b/sos/plugins/openstack_neutron.py +index 36de7cc..ab895c8 100644 +--- a/sos/plugins/openstack_neutron.py ++++ b/sos/plugins/openstack_neutron.py +@@ -14,6 +14,7 @@ + # along with this program; if not, write to the Free Software + # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + ++import glob + import os + import re + +@@ -50,6 +51,21 @@ class Neutron(Plugin): + + self.netns_dumps() + ++ def postproc(self): ++ protect_keys = [ ++ "rabbit_password", "qpid_password", "nova_admin_password", ++ "xenapi_connection_password", "password", "connection", ++ "admin_password", "metadata_proxy_shared_secret", "qpid_password", ++ "eapi_password", "crd_password", "primary_l3_host_password", ++ "serverauth", "ucsm_password", "ha_vrrp_auth_password", ++ "ssl_key_password", "nsx_password", "vcenter_password", ++ "edge_appliance_password", "tenant_admin_password", "apic_password" ++ ] ++ regexp = r"((?m)^\s*#*(%s)\s*=\s*)(.*)" % "|".join(protect_keys) ++ ++ for config_file in glob.glob("/etc/%s/*" % self.component_name): ++ self.do_file_sub(config_file, regexp, r"\1*********") ++ + def netns_dumps(self): + # It would've been beautiful if we could get parts of the networking + # plugin to run in different namespaces. There are a couple of options +-- +1.8.3.1 + diff --git a/sos-openstack_trove-plugin.patch b/sos-openstack_trove-plugin.patch new file mode 100644 index 0000000..3d78c0a --- /dev/null +++ b/sos-openstack_trove-plugin.patch @@ -0,0 +1,97 @@ +From 85d6ea5cdd32cf1b90a10ff0d50a14dcf24902f8 Mon Sep 17 00:00:00 2001 +From: Lee Yarwood +Date: Tue, 7 Apr 2015 18:26:42 +0100 +Subject: [PATCH] [openstack] New Openstack Trove (DBaaS) plugin. + +https://wiki.openstack.org/wiki/Trove + +Signed-off-by: Lee Yarwood +Signed-off-by: Adam Stokes +--- + sos/plugins/openstack_trove.py | 74 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 74 insertions(+) + create mode 100644 sos/plugins/openstack_trove.py + +diff --git a/sos/plugins/openstack_trove.py b/sos/plugins/openstack_trove.py +new file mode 100644 +index 0000000..7c8b661 +--- /dev/null ++++ b/sos/plugins/openstack_trove.py +@@ -0,0 +1,74 @@ ++# 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',) ++ option_list = [("log", "gathers openstack trove logs", "slow", True)] ++ ++ def setup(self): ++ self.add_copy_spec('/etc/trove/') ++ ++ if self.get_option('log'): ++ self.add_copy_spec('/var/log/trove') ++ ++ def postproc(self): ++ ++ protect_keys = [ ++ "dns_passkey", "nova_proxy_admin_pass", "rabbit_password", ++ "qpid_password", "connection", "sql_connection", "admin_password" ++ ] ++ ++ conf_list = [ ++ '/etc/trove/trove.conf', ++ '/etc/trove/trove-conductor.conf', ++ '/etc/trove/trove-guestmanager.conf', ++ '/etc/trove/trove-taskmanager.conf' ++ ] ++ ++ regexp = r"((?m)^\s*#*(%s)\s*=\s*)(.*)" % "|".join(protect_keys) ++ ++ for conf in conf_list: ++ self.do_file_sub(conf, regexp, r"\1*********") ++ ++ ++class DebianOpenStackTrove(OpenStackTrove, DebianPlugin, UbuntuPlugin): ++ ++ packages = [ ++ 'python-trove', ++ 'trove-common', ++ 'trove-api', ++ 'trove-taskmanager' ++ ] ++ ++ def setup(self): ++ super(DebianOpenStackTrove, self).setup() ++ ++ ++class RedHatOpenStackTrove(OpenStackTrove, RedHatPlugin): ++ ++ packages = ['openstack-trove'] ++ ++ def setup(self): ++ super(RedHatOpenStackTrove, self).setup() ++ ++# vim: et ts=4 sw=4 +-- +1.8.3.1 + diff --git a/sos-openvswitch-collect-logs-db-bridges.patch b/sos-openvswitch-collect-logs-db-bridges.patch new file mode 100644 index 0000000..a322add --- /dev/null +++ b/sos-openvswitch-collect-logs-db-bridges.patch @@ -0,0 +1,158 @@ +From 775b2bbfb28701ec2e687f0ece68a4558cef8740 Mon Sep 17 00:00:00 2001 +From: Lee Yarwood +Date: Tue, 17 Feb 2015 14:51:00 +0000 +Subject: [PATCH] [openvswitch] Capture additional output for OVS bridges. + +This includes `dump-flows` and `fdb/show` output useful for debugging +Openstack tenant and L3 networking issues. + +Signed-off-by: Lee Yarwood +--- + sos/plugins/openvswitch.py | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/sos/plugins/openvswitch.py b/sos/plugins/openvswitch.py +index 3611671..5200563 100644 +--- a/sos/plugins/openvswitch.py ++++ b/sos/plugins/openvswitch.py +@@ -32,6 +32,14 @@ class OpenVSwitch(Plugin): + # to the Open vSwitch server, avoiding hangs when running sosreport. + self.add_cmd_output("ovs-vsctl -t 5 show") + ++ # Gather additional output for each OVS bridge on the host. ++ br_list_result = self.call_ext_prog("ovs-vsctl list-br") ++ if br_list_result['status'] == 0: ++ for br in br_list_result['output'].splitlines(): ++ self.add_cmd_output("ovs-ofctl show %s" % br) ++ self.add_cmd_output("ovs-ofctl dump-flows %s" % br) ++ self.add_cmd_output("ovs-appctl fdb/show %s" % br) ++ + + class RedHatOpenVSwitch(OpenVSwitch, RedHatPlugin): + +-- +1.8.3.1 + +From 21aff64a58a3e0f3fc5065b2e18ca3d489e16a51 Mon Sep 17 00:00:00 2001 +From: Flavio Leitner +Date: Fri, 19 Jun 2015 21:55:56 -0300 +Subject: [PATCH] [openvswitch] capture the logs + +Both ovs-vswitchd.log and ovsdb-server.log are useful +for troubleshooting. + +Signed-off-by: Flavio Leitner +--- + sos/plugins/openvswitch.py | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/sos/plugins/openvswitch.py b/sos/plugins/openvswitch.py +index fbf3a90..1d75608 100644 +--- a/sos/plugins/openvswitch.py ++++ b/sos/plugins/openvswitch.py +@@ -24,6 +24,10 @@ class OpenVSwitch(Plugin): + profiles = ('network', 'virt') + + def setup(self): ++ self.add_copy_spec([ ++ "/var/log/openvswitch/ovs-vswitchd.log", ++ "/var/log/openvswitch/ovsdb-server.log" ++ ]) + # The '-s' option enables dumping of packet counters on the + # ports. + self.add_cmd_output("ovs-dpctl -s show") +-- +1.8.3.1 + +From f92205495113a8403066e911baeb4f5ee59c2101 Mon Sep 17 00:00:00 2001 +From: Flavio Leitner +Date: Fri, 19 Jun 2015 22:05:52 -0300 +Subject: [PATCH] [openvswitch] dump and capture the database + +The database contains all the vswitch configuration and +is essential to understand and replicate the environment. + +Signed-off-by: Flavio Leitner +--- + sos/plugins/openvswitch.py | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/sos/plugins/openvswitch.py b/sos/plugins/openvswitch.py +index 1d75608..4dd15b2 100644 +--- a/sos/plugins/openvswitch.py ++++ b/sos/plugins/openvswitch.py +@@ -44,6 +44,9 @@ class OpenVSwitch(Plugin): + self.add_cmd_output("ovs-ofctl dump-flows %s" % br) + self.add_cmd_output("ovs-appctl fdb/show %s" % br) + ++ # Gather the database. ++ self.add_cmd_output("ovsdb-client dump") ++ + + class RedHatOpenVSwitch(OpenVSwitch, RedHatPlugin): + +-- +1.8.3.1 + +From 4a57c54216242acb009fdb107d52712decfdfc1e Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Mon, 6 Jul 2015 17:31:44 +0100 +Subject: [PATCH] [openvswitch] consolidate self.add_cmd_output() calls + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/openvswitch.py | 28 ++++++++++++++++------------ + 1 file changed, 16 insertions(+), 12 deletions(-) + +diff --git a/sos/plugins/openvswitch.py b/sos/plugins/openvswitch.py +index 4dd15b2..8d691dc 100644 +--- a/sos/plugins/openvswitch.py ++++ b/sos/plugins/openvswitch.py +@@ -24,28 +24,32 @@ class OpenVSwitch(Plugin): + profiles = ('network', 'virt') + + def setup(self): ++ + self.add_copy_spec([ + "/var/log/openvswitch/ovs-vswitchd.log", + "/var/log/openvswitch/ovsdb-server.log" + ]) +- # The '-s' option enables dumping of packet counters on the +- # ports. +- self.add_cmd_output("ovs-dpctl -s show") + +- # The '-t 5' adds an upper bound on how long to wait to connect +- # to the Open vSwitch server, avoiding hangs when running sosreport. +- self.add_cmd_output("ovs-vsctl -t 5 show") ++ self.add_cmd_output([ ++ # The '-s' option enables dumping of packet counters on the ++ # ports. ++ "ovs-dpctl -s show", ++ # The '-t 5' adds an upper bound on how long to wait to connect ++ # to the Open vSwitch server, avoiding hangs when running sos. ++ "ovs-vsctl -t 5 show", ++ # Gather the database. ++ "ovsdb-client dump" ++ ]) + + # Gather additional output for each OVS bridge on the host. + br_list_result = self.call_ext_prog("ovs-vsctl list-br") + if br_list_result['status'] == 0: + for br in br_list_result['output'].splitlines(): +- self.add_cmd_output("ovs-ofctl show %s" % br) +- self.add_cmd_output("ovs-ofctl dump-flows %s" % br) +- self.add_cmd_output("ovs-appctl fdb/show %s" % br) +- +- # Gather the database. +- self.add_cmd_output("ovsdb-client dump") ++ self.add_cmd_output([ ++ "ovs-ofctl show %s" % br, ++ "ovs-ofctl dump-flows %s" % br, ++ "ovs-appctl fdb/show %s" % br ++ ]) + + + class RedHatOpenVSwitch(OpenVSwitch, RedHatPlugin): +-- +1.8.3.1 + diff --git a/sos-ovirt-engine-config-domain-list.patch b/sos-ovirt-engine-config-domain-list.patch new file mode 100644 index 0000000..f329d6a --- /dev/null +++ b/sos-ovirt-engine-config-domain-list.patch @@ -0,0 +1,36 @@ +From ae98e1e119d2abfe771cfa6c286e2e4e177d86d7 Mon Sep 17 00:00:00 2001 +From: Jake Hunsaker +Date: Tue, 16 Dec 2014 11:26:50 -0500 +Subject: [PATCH] [ovirt] Collect engine tunables and domain information. + +Currently sos does not capture engine-config values or domain information. +We should capture both of these as the tunables can help in troubleshooting. + +Similarly the domain information can help track AD/IPA issues. + +These can currently be dug out from the DB dump, however having them in a plaintext +file makes checking these much faster and easier, and a DB is not always available. + +Signed-off-by: Jake Hunsaker +Signed-off-by: Adam Stokes +--- + sos/plugins/ovirt.py | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/sos/plugins/ovirt.py b/sos/plugins/ovirt.py +index b097d93..9436ac6 100644 +--- a/sos/plugins/ovirt.py ++++ b/sos/plugins/ovirt.py +@@ -83,6 +83,9 @@ class Ovirt(Plugin, RedHatPlugin): + + 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", +-- +1.8.3.1 + diff --git a/sos-ovirt-engine-remove-password-leak.patch b/sos-ovirt-engine-remove-password-leak.patch new file mode 100644 index 0000000..4d86ae5 --- /dev/null +++ b/sos-ovirt-engine-remove-password-leak.patch @@ -0,0 +1,38 @@ +From 0aec209ec6870c6ec3cbb6e2209d35adb2b62009 Mon Sep 17 00:00:00 2001 +From: Sandro Bonazzola +Date: Tue, 16 Dec 2014 12:29:57 +0000 +Subject: [PATCH] [ovirt] remove ovirt-engine setup answer file password leak + +Signed-off-by: Sandro Bonazzola +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/ovirt.py | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/sos/plugins/ovirt.py b/sos/plugins/ovirt.py +index b169b90..407c918 100644 +--- a/sos/plugins/ovirt.py ++++ b/sos/plugins/ovirt.py +@@ -171,4 +171,19 @@ class Ovirt(Plugin, RedHatPlugin): + 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) ++ ) ++ + # vim: expandtab tabstop=4 shiftwidth=4 +-- +1.8.3.1 + diff --git a/sos-ovirt_hosted_engine-fix-exception-when-force-enabled.patch b/sos-ovirt_hosted_engine-fix-exception-when-force-enabled.patch new file mode 100644 index 0000000..c94d710 --- /dev/null +++ b/sos-ovirt_hosted_engine-fix-exception-when-force-enabled.patch @@ -0,0 +1,31 @@ +From f9aefde0d7f74867031a00b52f72d0ad1ff9463b Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Wed, 15 Oct 2014 15:51:13 +0100 +Subject: [PATCH] [ovirt_hosted_engine] fix exception when force-enabled + +Fixes #416. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/ovirt_hosted_engine.py | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/sos/plugins/ovirt_hosted_engine.py b/sos/plugins/ovirt_hosted_engine.py +index aee8bc0..02cb2b6 100644 +--- a/sos/plugins/ovirt_hosted_engine.py ++++ b/sos/plugins/ovirt_hosted_engine.py +@@ -56,8 +56,9 @@ class OvirtHostedEngine(Plugin, RedHatPlugin): + + all_setup_logs = glob.glob(self.SETUP_LOG_GLOB) + all_setup_logs.sort(reverse=True) +- # Add latest ovirt-hosted-engine-setup log file +- self.add_copy_spec(all_setup_logs[0]) ++ 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( +-- +1.9.3 + diff --git a/sos-parted-no-human-readable.patch b/sos-parted-no-human-readable.patch new file mode 100644 index 0000000..6ae4b3e --- /dev/null +++ b/sos-parted-no-human-readable.patch @@ -0,0 +1,32 @@ +From c77c14ecd3e7e35a331cef169b08ffcb318952c2 Mon Sep 17 00:00:00 2001 +From: Shane Bradley +Date: Tue, 20 Jan 2015 11:08:59 -0500 +Subject: [PATCH] [block] don't use parted human readable output + +Changed the parted command to return data in sectors units +instead of human readable form. + +Fixes #471. + +Signed-off-by: Shane Bradley +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/block.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sos/plugins/block.py b/sos/plugins/block.py +index 7984f0d..e02304c 100644 +--- a/sos/plugins/block.py ++++ b/sos/plugins/block.py +@@ -46,7 +46,7 @@ class Block(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin): + disk_path = os.path.join('/dev/', disk) + self.add_cmd_output([ + "udevadm info -ap /sys/block/%s" % (disk), +- "parted -s %s print" % (disk_path), ++ "parted -s %s unit s print" % (disk_path), + "fdisk -l %s" % disk_path + ]) + +-- +1.8.3.1 + diff --git a/sos-pcp-collect-config.patch b/sos-pcp-collect-config.patch new file mode 100644 index 0000000..009c234 --- /dev/null +++ b/sos-pcp-collect-config.patch @@ -0,0 +1,31 @@ +From 9cf393ac27728287927d2c1400e046a8c16679e7 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Wed, 11 Feb 2015 21:17:11 +0000 +Subject: [PATCH] [pcp] collect /etc/pcp.conf + +The file /etc/pcp.conf is added to list of lists that will be collected. + +Signed-off-by: Shane Bradley + +Fixes #465. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/pcp.py | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sos/plugins/pcp.py b/sos/plugins/pcp.py +index a696908..69872a3 100644 +--- a/sos/plugins/pcp.py ++++ b/sos/plugins/pcp.py +@@ -89,6 +89,7 @@ class Pcp(Plugin, RedHatPlugin, DebianPlugin): + 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 + ]) + +-- +1.8.3.1 + diff --git a/sos-pick-up-symlink-targets.patch b/sos-pick-up-symlink-targets.patch new file mode 100644 index 0000000..36dc409 --- /dev/null +++ b/sos-pick-up-symlink-targets.patch @@ -0,0 +1,26 @@ +From 4d8b5418b1cf218ef9746674ca5935a7f4f3983e Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Fri, 31 Jul 2015 10:21:17 +0100 +Subject: [PATCH] [Plugin] fix handling of symlinks in non-sysroot environments + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/__init__.py | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sos/plugins/__init__.py b/sos/plugins/__init__.py +index aed7496..6731b28 100644 +--- a/sos/plugins/__init__.py ++++ b/sos/plugins/__init__.py +@@ -163,6 +163,8 @@ class Plugin(object): + 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 +-- +1.8.3.1 + diff --git a/sos-plugin-limit-names-to-pc_name_max.patch b/sos-plugin-limit-names-to-pc_name_max.patch new file mode 100644 index 0000000..fca14ce --- /dev/null +++ b/sos-plugin-limit-names-to-pc_name_max.patch @@ -0,0 +1,118 @@ +From 48a99c95078bab306cb56bb1a05420d88bf15a64 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Mon, 20 Oct 2014 16:12:01 +0100 +Subject: [PATCH] [plugin] limit names to PC_NAME_MAX + +Commit 8bf7b0c removed the truncation of mangled command names to +64 chars. This causes problems for some plugins (e.g. Issue #415) +that generate long enough command lines to hit system name length +limits. + +Instead of arbitrarily limiting to 64 characters limit to the +lesser of the archive format limit (if present) or the value of +PC_NAME_MAX for any intermediate FileCacheArchive path. + +Signed-off-by: Bryn M. Reeves +--- + sos/archive.py | 18 ++++++++++++++++++ + sos/plugins/__init__.py | 7 ++++--- + tests/plugin_tests.py | 12 ++++++++---- + 3 files changed, 30 insertions(+), 7 deletions(-) + +diff --git a/sos/archive.py b/sos/archive.py +index 2e42bbd..6063625 100644 +--- a/sos/archive.py ++++ b/sos/archive.py +@@ -98,6 +98,12 @@ class Archive(object): + 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 +@@ -206,6 +212,13 @@ class FileCacheArchive(Archive): + 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 + +@@ -355,6 +368,11 @@ class TarFileArchive(FileCacheArchive): + 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: +diff --git a/sos/plugins/__init__.py b/sos/plugins/__init__.py +index 3e39100..b289144 100644 +--- a/sos/plugins/__init__.py ++++ b/sos/plugins/__init__.py +@@ -42,11 +42,11 @@ def regex_findall(regex, fname): + return [] + + +-def _mangle_command(command): +- # FIXME: this can be improved ++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 + + +@@ -518,7 +518,8 @@ class Plugin(object): + return grep(regexp, *fnames) + + def _mangle_command(self, exe): +- return _mangle_command(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.""" +diff --git a/tests/plugin_tests.py b/tests/plugin_tests.py +index 817e4f2..f73a003 100644 +--- a/tests/plugin_tests.py ++++ b/tests/plugin_tests.py +@@ -115,10 +115,14 @@ class PluginToolTests(unittest.TestCase): + self.assertEquals(matches, []) + + def test_mangle_command(self): +- self.assertEquals("foo", _mangle_command("/usr/bin/foo")) +- self.assertEquals("foo_-x", _mangle_command("/usr/bin/foo -x")) +- self.assertEquals("foo_--verbose", _mangle_command("/usr/bin/foo --verbose")) +- self.assertEquals("foo_.path.to.stuff", _mangle_command("/usr/bin/foo /path/to/stuff")) ++ name_max = 255 ++ self.assertEquals("foo", _mangle_command("/usr/bin/foo", name_max)) ++ self.assertEquals("foo_-x", _mangle_command("/usr/bin/foo -x", name_max)) ++ self.assertEquals("foo_--verbose", _mangle_command("/usr/bin/foo --verbose", name_max)) ++ self.assertEquals("foo_.path.to.stuff", _mangle_command("/usr/bin/foo /path/to/stuff", name_max)) ++ longcmd ="foo is " + "a" * 256 + " long_command" ++ expected = longcmd[0:name_max].replace(' ', '_') ++ self.assertEquals(expected, _mangle_command(longcmd, name_max)) + + + class PluginTests(unittest.TestCase): +-- +1.9.3 + diff --git a/sos-plugins-allow-discard-stderr.patch b/sos-plugins-allow-discard-stderr.patch new file mode 100644 index 0000000..c9d32d9 --- /dev/null +++ b/sos-plugins-allow-discard-stderr.patch @@ -0,0 +1,137 @@ +From 7b2885740216f8e4076781e088d37cb7b4f96f63 Mon Sep 17 00:00:00 2001 +From: John Haxby +Date: Wed, 28 Jan 2015 19:30:29 +0000 +Subject: [PATCH] [plugins,utilities] Allow commands to discard stderr + +Just add "stderr=False" to add_cmd_output() if you don't want the +command's stderr in the sosreport. + +Signed-off-by: John Haxby + +Minor edits for pep8 conformance and to shorten the argument name. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/__init__.py | 29 +++++++++++++++++------------ + sos/utilities.py | 5 +++-- + 2 files changed, 20 insertions(+), 14 deletions(-) +--- + sos/plugins/__init__.py | 33 +++++++++++++++++++++------------ + sos/utilities.py | 5 +++-- + 2 files changed, 24 insertions(+), 14 deletions(-) + +diff --git a/sos/plugins/__init__.py b/sos/plugins/__init__.py +index 4fd85be..9d126a5 100644 +--- a/sos/plugins/__init__.py ++++ b/sos/plugins/__init__.py +@@ -460,8 +460,9 @@ class Plugin(object): + self.copy_paths.update(copy_paths) + self._log_info("added copyspec '%s'" % copyspec) + +- def get_command_output(self, prog, timeout=300, runat=None): +- result = sos_get_command_output(prog, timeout=timeout, runat=runat) ++ def get_command_output(self, prog, timeout=300, runat=None, stderr=True): ++ result = sos_get_command_output(prog, timeout=timeout, runat=runat, ++ stderr=stderr) + if result['status'] == 124: + self._log_warn("command '%s' timed out after %ds" + % (prog, timeout)) +@@ -470,11 +471,12 @@ class Plugin(object): + self._log_debug("could not run '%s': command not found" % prog) + return result + +- def call_ext_prog(self, prog, timeout=300, runat=None): ++ def call_ext_prog(self, prog, timeout=300, runat=None, stderr=True): + """Execute a command independantly of the output gathering part of + sosreport. + """ +- return self.get_command_output(prog, timeout=timeout, runat=runat) ++ return self.get_command_output(prog, timeout=timeout, runat=runat, ++ stderr=True) + + def check_ext_prog(self, prog): + """Execute a command independently of the output gathering part of +@@ -484,15 +486,19 @@ class Plugin(object): + return self.call_ext_prog(prog)['status'] == 0 + + def add_cmd_output(self, cmds, suggest_filename=None, +- root_symlink=None, timeout=300, runat=None): ++ root_symlink=None, timeout=300, runat=None, ++ stderr=True): + """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, runat) +- _logstr = "packed command tuple: ('%s', '%s', '%s', %s, '%s')" ++ cmdt = ( ++ cmd, suggest_filename, root_symlink, timeout, runat, stderr ++ ) ++ _tuplefmt = "('%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) +@@ -547,12 +553,13 @@ class Plugin(object): + + def get_cmd_output_now(self, exe, suggest_filename=None, + root_symlink=False, timeout=300, +- runat=None): ++ runat=None, stderr=True): + """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, runat=runat) ++ result = self.get_command_output(exe, timeout=timeout, runat=runat, ++ stderr=stderr) + # 126 means 'found but not executable' + if result['status'] == 126 or result['status'] == 127: + return None +@@ -601,13 +608,15 @@ class Plugin(object): + + def _collect_cmd_output(self): + for progs in zip(self.collect_cmds): +- prog, suggest_filename, root_symlink, timeout, runat = progs[0] ++ (prog, suggest_filename, root_symlink, timeout, runat, stderr ++ ) = progs[0] + self._log_debug("unpacked command tuple: " +- + "('%s', '%s', '%s', %s, '%s')" % progs[0]) ++ + "('%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, runat=runat) ++ timeout=timeout, runat=runat, ++ stderr=stderr) + + def _collect_strings(self): + for string, file_name in self.copy_strings: +diff --git a/sos/utilities.py b/sos/utilities.py +index 2638ce4..db340f8 100644 +--- a/sos/utilities.py ++++ b/sos/utilities.py +@@ -120,7 +120,7 @@ def is_executable(command): + return any(os.access(path, os.X_OK) for path in candidates) + + +-def sos_get_command_output(command, timeout=300, runat=None): ++def sos_get_command_output(command, timeout=300, runat=None, stderr=True): + """Execute a command through the system shell. First checks to see if the + requested command is executable. Returns (returncode, stdout, 0)""" + def _child_chdir(): +@@ -142,7 +142,8 @@ def sos_get_command_output(command, timeout=300, runat=None): + command = command.encode('utf-8', 'ignore') + args = shlex.split(command) + try: +- p = Popen(args, shell=False, stdout=PIPE, stderr=STDOUT, ++ p = Popen(args, shell=False, stdout=PIPE, ++ stderr=STDOUT if stderr else PIPE, + bufsize=-1, env=cmd_env, close_fds=True, + preexec_fn=_child_chdir) + except OSError as e: +-- +1.8.3.1 + diff --git a/sos-policies-PackageManager-timeout.patch b/sos-policies-PackageManager-timeout.patch new file mode 100644 index 0000000..4fd3e8e --- /dev/null +++ b/sos-policies-PackageManager-timeout.patch @@ -0,0 +1,100 @@ +From 3a2ad99c71dae022cfb7fb02e11473001c50ae23 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Tue, 27 Jan 2015 13:07:52 +0000 +Subject: [PATCH] [policies] run PackageManager query_command under timeout + +PackageManager query commands may block due to file system locks +or problems with the package database. Run the query command with +a timeout of 30s and exit if the timeout expires. + +Signed-off-by: Aruna Balakrishnaiah +Signed-off-by: Bryn M. Reeves + +--- +Changes from v3: + Add default timeout instead of making it configurable + Add print function instead of error() + +Changes from v2: + Introduce timeout in shell_out wrapper + +Changes from v1: + Addressed issues of the maintainer + Introduce timeout instead of relying on yum. +--- + sos/policies/__init__.py | 3 ++- + sos/policies/redhat.py | 10 +++++++++- + sos/utilities.py | 4 ++-- + 3 files changed, 13 insertions(+), 4 deletions(-) + +diff --git a/sos/policies/__init__.py b/sos/policies/__init__.py +index 9fcbd55..34a2f6a 100644 +--- a/sos/policies/__init__.py ++++ b/sos/policies/__init__.py +@@ -56,6 +56,7 @@ class PackageManager(object): + """ + + query_command = None ++ timeout = 30 + + def __init__(self, query_command=None): + self.packages = {} +@@ -92,7 +93,7 @@ class PackageManager(object): + version': 'major.minor.version'}} + """ + if self.query_command: +- pkg_list = shell_out(self.query_command).splitlines() ++ pkg_list = shell_out(self.query_command, self.timeout).splitlines() + for pkg in pkg_list: + if '|' not in pkg: + continue +diff --git a/sos/policies/redhat.py b/sos/policies/redhat.py +index 2219246..38510d9 100644 +--- a/sos/policies/redhat.py ++++ b/sos/policies/redhat.py +@@ -15,6 +15,7 @@ + # 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 + +@@ -46,8 +47,15 @@ class RedHatPolicy(LinuxPolicy): + 'rpm -qa --queryformat "%{NAME}|%{VERSION}\\n"') + 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 self.package_manager.all_pkgs()['filesystem']['version'][0] == '3': ++ 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" +diff --git a/sos/utilities.py b/sos/utilities.py +index 51909c6..2638ce4 100644 +--- a/sos/utilities.py ++++ b/sos/utilities.py +@@ -180,11 +180,11 @@ def import_module(module_fqname, superclasses=None): + return modules + + +-def shell_out(cmd, runat=None): ++def shell_out(cmd, timeout=30, 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, runat=runat)['output'] ++ return sos_get_command_output(cmd, timeout=timeout, runat=runat)['output'] + + + class ImporterHelper(object): +-- +1.8.3.1 + diff --git a/sos-powerpc-allow-powerpc-plugin-to-run-on-ppc64le.patch b/sos-powerpc-allow-powerpc-plugin-to-run-on-ppc64le.patch new file mode 100644 index 0000000..4bf9824 --- /dev/null +++ b/sos-powerpc-allow-powerpc-plugin-to-run-on-ppc64le.patch @@ -0,0 +1,31 @@ +From 988fee7e6d0c2c91cf1f2c9363d4e3cea7244163 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Thu, 2 Oct 2014 17:25:17 +0100 +Subject: [PATCH] [powerpc] allow PowerPC plugin to run on ppc64le + +The plugin currently tests whether policy().get_arch() is equal +to "ppc64". On little endian PowerPC machines this method returns +"ppc64le". Change the check_enabled() method to test whether the +returned string contains "ppc64". + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/powerpc.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sos/plugins/powerpc.py b/sos/plugins/powerpc.py +index 896d1d4..39b52f6 100644 +--- a/sos/plugins/powerpc.py ++++ b/sos/plugins/powerpc.py +@@ -27,7 +27,7 @@ class PowerPC(Plugin, RedHatPlugin, UbuntuPlugin, DebianPlugin): + profiles = ('system', 'hardware') + + def check_enabled(self): +- return (self.policy().get_arch() == "ppc64") ++ return "ppc64" in self.policy().get_arch() + + def setup(self): + try: +-- +1.9.3 + diff --git a/sos-puppet-collect-config.patch b/sos-puppet-collect-config.patch new file mode 100644 index 0000000..6677894 --- /dev/null +++ b/sos-puppet-collect-config.patch @@ -0,0 +1,68 @@ +From c5f969e8a79a2bc7e0280e11e4a02599552b326f Mon Sep 17 00:00:00 2001 +From: Shane Bradley +Date: Tue, 20 Jan 2015 11:33:31 -0500 +Subject: [PATCH] [puppet] adding new plugin for puppet + +Added a new plugin to collect files for puppet. + +Fixes: #473. + +Signed-off-by: Shane Bradley +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/puppet.py | 43 +++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 43 insertions(+) + create mode 100644 sos/plugins/puppet.py + +diff --git a/sos/plugins/puppet.py b/sos/plugins/puppet.py +new file mode 100644 +index 0000000..4da95a2 +--- /dev/null ++++ b/sos/plugins/puppet.py +@@ -0,0 +1,43 @@ ++# 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 +-- +1.8.3.1 + diff --git a/sos-rabbitmq-cluster-status.patch b/sos-rabbitmq-cluster-status.patch new file mode 100644 index 0000000..a7d06d6 --- /dev/null +++ b/sos-rabbitmq-cluster-status.patch @@ -0,0 +1,28 @@ +From 786f74a79f6baec716be8c8a05da90b5c63848d0 Mon Sep 17 00:00:00 2001 +From: Jorge Niedbalski +Date: Fri, 14 Nov 2014 11:43:31 -0300 +Subject: [PATCH] [plugins/rabbitmq] Added cluster_status command output + +* Added the 'rabbitmqctl cluster_status' output command + +Signed-off-by: Jorge Niedbalski R. +--- + sos/plugins/rabbitmq.py | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sos/plugins/rabbitmq.py b/sos/plugins/rabbitmq.py +index ee09fa3..3e81d66 100644 +--- a/sos/plugins/rabbitmq.py ++++ b/sos/plugins/rabbitmq.py +@@ -25,6 +25,8 @@ class RabbitMQ(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin): + + def setup(self): + self.add_cmd_output("rabbitmqctl report") ++ self.add_cmd_output("rabbitmqctl cluster_status") ++ + self.add_copy_spec("/etc/rabbitmq/*") + self.add_copy_spec_limit("/var/log/rabbitmq/*", + sizelimit=self.get_option('log_size')) +-- +1.8.3.1 + diff --git a/sos-redact-secrets-from-sahara-config.patch b/sos-redact-secrets-from-sahara-config.patch new file mode 100644 index 0000000..a8cb062 --- /dev/null +++ b/sos-redact-secrets-from-sahara-config.patch @@ -0,0 +1,35 @@ +From 706e523d608b588cfd70b2dfa957feafe0645796 Mon Sep 17 00:00:00 2001 +From: Rohan Kanade +Date: Mon, 15 Jun 2015 20:24:10 +0530 +Subject: [PATCH] [openstack_sahara] redact secrets from sahara configuration + +Signed-off-by: Rohan Kanade +--- + sos/plugins/openstack_sahara.py | 11 +++++++++++ + 1 files changed, 11 insertions(+), 0 deletions(-) + +diff --git a/sos/plugins/openstack_sahara.py b/sos/plugins/openstack_sahara.py +index f0b95e4..9d971ba 100644 +--- a/sos/plugins/openstack_sahara.py ++++ b/sos/plugins/openstack_sahara.py +@@ -31,6 +31,17 @@ class OpenStackSahara(Plugin): + if self.get_option("log"): + self.add_copy_spec("/var/log/sahara/") + ++ def postproc(self): ++ protect_keys = [ ++ 'memcache_secret_key', 'qpid_password', 'rabbit_password', ++ 'admin_password', 'password', 'ssl_key_password', ++ 'admin_token', 'connection' ++ ] ++ ++ regexp = r"((?m)^\s*#*(%s)\s*=\s*)(.*)" % "|".join(protect_keys) ++ ++ self.do_file_sub('/etc/sahara/sahara.conf', regexp, r"\1*********") ++ + + class DebianOpenStackSahara(OpenStackSahara, DebianPlugin, UbuntuPlugin): + """OpenStackSahara related information for Debian based distributions.""" +-- +1.7.1 + diff --git a/sos-sap-hana-netweaver-vhostmd-plugins.patch b/sos-sap-hana-netweaver-vhostmd-plugins.patch new file mode 100644 index 0000000..52c78e3 --- /dev/null +++ b/sos-sap-hana-netweaver-vhostmd-plugins.patch @@ -0,0 +1,612 @@ +From e768bf71c96317bc64b643ab9262cb88f1d9058c Mon Sep 17 00:00:00 2001 +From: Luca Miccini +Date: Tue, 24 Feb 2015 18:38:20 +0100 +Subject: [PATCH 1/7] [saphana] add SAP HANA plugin + +Add a plugin for the SAP HANA component and add it to a new 'sap' +profile. + +Signed-off-by: Luca Miccini +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/saphana.py | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 84 insertions(+) + create mode 100644 sos/plugins/saphana.py + +diff --git a/sos/plugins/saphana.py b/sos/plugins/saphana.py +new file mode 100644 +index 0000000..2ff26f5 +--- /dev/null ++++ b/sos/plugins/saphana.py +@@ -0,0 +1,84 @@ ++# 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 +-- +1.8.3.1 + + +From 581b05584410e48be998c98efe25ab9783641d1b Mon Sep 17 00:00:00 2001 +From: Luca Miccini +Date: Fri, 13 Mar 2015 12:43:08 +0100 +Subject: [PATCH 2/7] [vhostmd] add new plugin + +Add a plugin for the Virtual Host Metrics Daemon (vhostmd) to +collect VM performance metrics from the system. + +Fixes #527. + +Signed-off-by: Luca Miccini +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/vhostmd.py | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 52 insertions(+) + create mode 100644 sos/plugins/vhostmd.py + +diff --git a/sos/plugins/vhostmd.py b/sos/plugins/vhostmd.py +new file mode 100644 +index 0000000..6711945 +--- /dev/null ++++ b/sos/plugins/vhostmd.py +@@ -0,0 +1,52 @@ ++# 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 vhostmd(Plugin, RedHatPlugin): ++ """vhostmd virtualization metrics collection ++ """ ++ ++ plugin_name = 'vhostmd' ++ profiles = ['sap'] ++ ++ packages = ['virt-what'] ++ ++ def setup(self): ++ vw = self.get_command_output("virt-what")['output'].splitlines() ++ ++ if not vw: ++ return ++ ++ if "vmware" in vw or "kvm" in vw or "xen" in vw: ++ # if vm-dump-metrics is installed use it ++ if self.is_installed("vm-dump-metrics"): ++ self.add_cmd_output("vm-dump-metrics", ++ suggest_filename="virt_metrics") ++ else: ++ # otherwise use the raw vhostmd disk presented (256k size) ++ d = self.get_command_output("lsblk -d") ++ for disk in d['output'].splitlines(): ++ if "256K" in disk: ++ dev = disk.split()[0] ++ check = self.get_command_output( ++ "dd if=/dev/%s bs=25 count=1" % dev) ++ if 'metric' in check['output']: ++ self.add_cmd_output("dd if=/dev/%s bs=256k count=1" ++ % dev, ++ suggest_filename="virt_\ ++ metrics") ++ ++# vim: et ts=4 sw=4 +-- +1.8.3.1 + + +From 8a710151c792a5f8bddba33de29976bb218b6701 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Tue, 30 Jun 2015 17:55:58 +0100 +Subject: [PATCH 3/7] [vhostmd] add plugin to the system and virt profiles + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/vhostmd.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sos/plugins/vhostmd.py b/sos/plugins/vhostmd.py +index 6711945..786a7c1 100644 +--- a/sos/plugins/vhostmd.py ++++ b/sos/plugins/vhostmd.py +@@ -20,7 +20,7 @@ class vhostmd(Plugin, RedHatPlugin): + """ + + plugin_name = 'vhostmd' +- profiles = ['sap'] ++ profiles = ['sap', 'virt', 'system'] + + packages = ['virt-what'] + +-- +1.8.3.1 + + +From a5824f209c000d1a69ef305dd69f105400de3f4a Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Tue, 30 Jun 2015 18:00:28 +0100 +Subject: [PATCH 4/7] [vhostmd] enumerate disks via /sys/block instead of + "lsblk -d" + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/vhostmd.py | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/sos/plugins/vhostmd.py b/sos/plugins/vhostmd.py +index 786a7c1..0a86fb5 100644 +--- a/sos/plugins/vhostmd.py ++++ b/sos/plugins/vhostmd.py +@@ -13,6 +13,7 @@ + # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + from sos.plugins import Plugin, RedHatPlugin ++import os + + + class vhostmd(Plugin, RedHatPlugin): +@@ -31,14 +32,16 @@ class vhostmd(Plugin, RedHatPlugin): + return + + if "vmware" in vw or "kvm" in vw or "xen" in vw: +- # if vm-dump-metrics is installed use it + if self.is_installed("vm-dump-metrics"): ++ # if vm-dump-metrics is installed use it + self.add_cmd_output("vm-dump-metrics", + suggest_filename="virt_metrics") + else: + # otherwise use the raw vhostmd disk presented (256k size) +- d = self.get_command_output("lsblk -d") +- for disk in d['output'].splitlines(): ++ sysblock = "/sys/block" ++ if not os.path.isdir(sysblock): ++ return ++ for disk in os.listdir(sysblock): + if "256K" in disk: + dev = disk.split()[0] + check = self.get_command_output( +-- +1.8.3.1 + + +From a191fc379d2ee3b4b42014eec4c3f83a6e423761 Mon Sep 17 00:00:00 2001 +From: Luca Miccini +Date: Tue, 24 Feb 2015 18:40:07 +0100 +Subject: [PATCH 5/7] [sapnw] add SAP NetWeaver plugin + +Closes #516. + +Signed-off-by: Luca Miccini +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/sapnw.py | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 131 insertions(+) + create mode 100644 sos/plugins/sapnw.py + +diff --git a/sos/plugins/sapnw.py b/sos/plugins/sapnw.py +new file mode 100644 +index 0000000..d2be8dd +--- /dev/null ++++ b/sos/plugins/sapnw.py +@@ -0,0 +1,131 @@ ++# 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 sets import Set ++from sos.plugins import Plugin, RedHatPlugin ++ ++ ++class sapnw(Plugin, RedHatPlugin): ++ """SAP NetWeaver""" ++ ++ files = ['/usr/sap'] ++ ++ def setup(self): ++ ++ # list installed instances ++ self.add_cmd_output("/usr/sap/hostctrl/exe/saphostctrl \ ++ -function ListInstances", ++ suggest_filename="SAPInstances_List") ++ # list installed sap dbs ++ self.add_cmd_output("/usr/sap/hostctrl/exe/saphostctrl \ ++ -function ListDatabases", ++ suggest_filename="SAPDatabases_List") ++ ++ # list defined instances and guess profiles out of them ++ # (good for HA setups with virtual hostnames) ++ # using sap host control agent ++ ++ p = self.get_command_output( ++ "/usr/sap/hostctrl/exe/saphostctrl -function ListInstances") ++ ++ sidsunique = Set([]) ++ ++ # Cycle through all the instances, get 'sid' 'instance_number' ++ # and 'vhost' to determine the proper profile ++ for line in p['output'].splitlines(): ++ if "DAA" not in line: ++ fields = line.strip().split() ++ sid = fields[3] ++ inst = fields[5] ++ vhost = fields[7] ++ sidsunique.add(sid) ++ p = os.listdir("/usr/sap/%s/SYS/profile/" % sid) ++ for line in p: ++ if sid in line and inst in line and vhost in line: ++ ldenv = 'LD_LIBRARY_PATH=/usr/sap/%s/SYS/exe/run' % sid ++ pt = '/usr/sap/%s/SYS/exe/uc/linuxx86_64' % sid ++ profile = line.strip() ++ 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: ++ c = self.get_command_output("ls /usr/sap/%s/" % sid) ++ for line in c['output'].splitlines(): ++ 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) ++ ++ # get the installed db's ++ d = self.get_command_output( ++ '/usr/sap/hostctrl/exe/saphostctrl -function ListDatabases') ++ ++ for line in d['output'].splitlines(): ++ if "Instance name" in line: ++ fields = line.strip().split() ++ dbadm = fields[2][:-1] ++ dbtype = fields[8][:-1] ++ sid = dbadm[3:].upper() ++ ++ if dbtype == 'db6': ++ self.add_cmd_output( ++ "su - %s -c \"db2 get dbm cfg\"" ++ % dbadm, suggest_filename="%s_%s_db2_info" ++ % (sid, dbadm)) ++ ++ if dbtype == 'sap': ++ sid = fields[2][:-1] ++ self.add_cmd_output( ++ "cat /sapdb/%s/data/config/%s.pah" ++ % (sid, sid), ++ suggest_filename="%s_%s_maxdb_info" ++ % (sid, dbadm)) ++ ++ if dbtype == 'ora': ++ sid = fields[2][:-1] ++ self.add_cmd_output( ++ "cat /oracle/%s/*/dbs/init.ora" % sid, ++ suggest_filename="%s_oracle_init.ora" % sid) ++ ++ # if sapconf available run it in check mode ++ if os.path.isfile("/usr/bin/sapconf"): ++ self.add_cmd_output( ++ "/usr/bin/sapconf -n", suggest_filename="sapconf_checkmode") ++ ++# vim: et ts=4 sw=4 +-- +1.8.3.1 + + +From 1d4185aa916703370f605f87341aa74563f06aa5 Mon Sep 17 00:00:00 2001 +From: Luca Miccini +Date: Mon, 2 Mar 2015 12:01:23 +0100 +Subject: [PATCH 6/7] [sapnw] add 'sapnw' as member of the 'sap' profile + +Signed-off-by: Luca Miccini +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/sapnw.py | 74 +++++++++++++++++++++++++++++----------------------- + 1 file changed, 41 insertions(+), 33 deletions(-) + +diff --git a/sos/plugins/sapnw.py b/sos/plugins/sapnw.py +index d2be8dd..521556b 100644 +--- a/sos/plugins/sapnw.py ++++ b/sos/plugins/sapnw.py +@@ -17,46 +17,54 @@ from sets import Set + 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 setup(self): + + # list installed instances +- self.add_cmd_output("/usr/sap/hostctrl/exe/saphostctrl \ +- -function ListInstances", +- suggest_filename="SAPInstances_List") ++ inst_out = self.get_cmd_output_now("/usr/sap/hostctrl/exe/saphostctrl \ ++ -function ListInstances", ++ suggest_filename="SAPInstances") + # list installed sap dbs +- self.add_cmd_output("/usr/sap/hostctrl/exe/saphostctrl \ +- -function ListDatabases", +- suggest_filename="SAPDatabases_List") +- +- # list defined instances and guess profiles out of them +- # (good for HA setups with virtual hostnames) +- # using sap host control agent +- +- p = self.get_command_output( +- "/usr/sap/hostctrl/exe/saphostctrl -function ListInstances") ++ db_out = self.get_cmd_output_now("/usr/sap/hostctrl/exe/saphostctrl \ ++ -function ListDatabases", ++ suggest_filename="SAPDatabases") + + sidsunique = Set([]) + + # Cycle through all the instances, get 'sid' 'instance_number' + # and 'vhost' to determine the proper profile +- for line in p['output'].splitlines(): ++ 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) +- p = os.listdir("/usr/sap/%s/SYS/profile/" % sid) +- for line in p: ++ 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" +@@ -67,13 +75,15 @@ class sapnw(Plugin, RedHatPlugin): + self.add_cmd_output( + "env -i %s %s/sapcontrol -nr %s \ + -function GetProcessList" % (ldenv, pt, inst), +- suggest_filename="%s_%s_GetProcList" % (sid, 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)) ++ suggest_filename="%s_%s_GetVersInfo" ++ % (sid, inst)) + + # collect adm user environment + lowsid = sid.lower() +@@ -85,18 +95,18 @@ class sapnw(Plugin, RedHatPlugin): + + # traverse the sids list, collecting info about dbclient + for sid in sidsunique: +- c = self.get_command_output("ls /usr/sap/%s/" % sid) +- for line in c['output'].splitlines(): ++ 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) ++ % (sid, line), suggest_filename="%s_dbclient" ++ % sid) + +- # get the installed db's +- d = self.get_command_output( +- '/usr/sap/hostctrl/exe/saphostctrl -function ListDatabases') ++ if not db_out: ++ return ++ dbl = open(db_out, "r").read().splitlines() + +- for line in d['output'].splitlines(): ++ for line in dbl: + if "Instance name" in line: + fields = line.strip().split() + dbadm = fields[2][:-1] +@@ -104,24 +114,22 @@ class sapnw(Plugin, RedHatPlugin): + 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_cmd_output( +- "cat /sapdb/%s/data/config/%s.pah" +- % (sid, sid), +- suggest_filename="%s_%s_maxdb_info" +- % (sid, dbadm)) ++ self.add_copy_spec( ++ "/sapdb/%s/data/config/%s.pah" % (sid, sid)) + + if dbtype == 'ora': ++ # Oracle + sid = fields[2][:-1] +- self.add_cmd_output( +- "cat /oracle/%s/*/dbs/init.ora" % sid, +- suggest_filename="%s_oracle_init.ora" % sid) ++ self.add_copy_spec("/oracle/%s/*/dbs/init.ora" % sid) + + # if sapconf available run it in check mode + if os.path.isfile("/usr/bin/sapconf"): +-- +1.8.3.1 + + +From 5ac02f4fbc38992f23aa1f44974f74f7c4e16ea5 Mon Sep 17 00:00:00 2001 +From: Luca Miccini +Date: Wed, 11 Mar 2015 15:19:49 +0100 +Subject: [PATCH 7/7] [sapnw] add sybase ASE collection + +Signed-off-by: Luca Miccini +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/sapnw.py | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/sos/plugins/sapnw.py b/sos/plugins/sapnw.py +index 521556b..e18978f 100644 +--- a/sos/plugins/sapnw.py ++++ b/sos/plugins/sapnw.py +@@ -131,6 +131,11 @@ class sapnw(Plugin, RedHatPlugin): + 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)) ++ + # if sapconf available run it in check mode + if os.path.isfile("/usr/bin/sapconf"): + self.add_cmd_output( +-- +1.8.3.1 + diff --git a/sos-sapnw-cmd-output-check.patch b/sos-sapnw-cmd-output-check.patch new file mode 100644 index 0000000..7c90b77 --- /dev/null +++ b/sos-sapnw-cmd-output-check.patch @@ -0,0 +1,153 @@ +From 24fb011755e655127b7e09f4c02275539666b4b2 Mon Sep 17 00:00:00 2001 +From: Pavel Moravec +Date: Wed, 29 Jul 2015 14:47:19 +0200 +Subject: [PATCH] [sapnw] uses a deprecated Sets module + +Use built-in set class instead of deprecated Set for sidsunique + +Resolves: #608 + +Signed-off-by: Pavel Moravec +Signed-off-by: Adam Stokes +--- + sos/plugins/sapnw.py | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/sos/plugins/sapnw.py b/sos/plugins/sapnw.py +index e18978f..59beff2 100644 +--- a/sos/plugins/sapnw.py ++++ b/sos/plugins/sapnw.py +@@ -13,7 +13,6 @@ + # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + import os +-from sets import Set + from sos.plugins import Plugin, RedHatPlugin + + +@@ -44,7 +43,7 @@ class sapnw(Plugin, RedHatPlugin): + -function ListDatabases", + suggest_filename="SAPDatabases") + +- sidsunique = Set([]) ++ sidsunique = set() + + # Cycle through all the instances, get 'sid' 'instance_number' + # and 'vhost' to determine the proper profile +-- +1.8.3.1 + +From 10059897ceb0755bab844011f11ea6c6af8794ae Mon Sep 17 00:00:00 2001 +From: Pavel Moravec +Date: Tue, 28 Jul 2015 13:50:54 +0200 +Subject: [PATCH] [sapnw] Add check if saphostctrl is not present + +Split listing&collecting instances and dbs from lengthy setup(). + +Break execution when "inst_out = self.get_cmd_output_now" returns None. + +db_out is already checked this way. + +Resolves: #614 + +Signed-off-by: Pavel Moravec +--- + sos/plugins/sapnw.py | 30 +++++++++++++++++------------- + 1 file changed, 17 insertions(+), 13 deletions(-) + +diff --git a/sos/plugins/sapnw.py b/sos/plugins/sapnw.py +index 59beff2..d2c93ec 100644 +--- a/sos/plugins/sapnw.py ++++ b/sos/plugins/sapnw.py +@@ -32,20 +32,16 @@ class sapnw(Plugin, RedHatPlugin): + + files = ['/usr/sap'] + +- def setup(self): +- ++ 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") +- # list installed sap dbs +- db_out = self.get_cmd_output_now("/usr/sap/hostctrl/exe/saphostctrl \ +- -function ListDatabases", +- suggest_filename="SAPDatabases") ++ if not inst_out: ++ return + + sidsunique = set() +- +- # Cycle through all the instances, get 'sid' 'instance_number' ++ # 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: +@@ -101,10 +97,15 @@ class sapnw(Plugin, RedHatPlugin): + % (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() + ++ dbl = open(db_out, "r").read().splitlines() + for line in dbl: + if "Instance name" in line: + fields = line.strip().split() +@@ -135,9 +136,12 @@ class sapnw(Plugin, RedHatPlugin): + sid = fields[2][:-1] + self.add_copy_spec("/sybase/%s/ASE*/%s.cfg" % (sid, sid)) + +- # if sapconf available run it in check mode +- if os.path.isfile("/usr/bin/sapconf"): +- self.add_cmd_output( +- "/usr/bin/sapconf -n", suggest_filename="sapconf_checkmode") ++ def setup(self): ++ collect_list_instances() ++ collect_list_dbs() ++ ++ # run sapconf in check mode ++ self.add_cmd_output("sapconf -n", ++ suggest_filename="sapconf_checkmode") + + # vim: et ts=4 sw=4 +-- +1.8.3.1 + +From 1f83971325629cb3f470dac74de1be49f095118e Mon Sep 17 00:00:00 2001 +From: Pavel Moravec +Date: Tue, 4 Aug 2015 10:44:37 +0200 +Subject: [PATCH] [sapnw] call self methods properly + +Call methods from the self class within "self." scope. + +Signed-off-by: Pavel Moravec +--- + sos/plugins/sapnw.py | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/sos/plugins/sapnw.py b/sos/plugins/sapnw.py +index d2c93ec..be8c4b9 100644 +--- a/sos/plugins/sapnw.py ++++ b/sos/plugins/sapnw.py +@@ -137,8 +137,8 @@ class sapnw(Plugin, RedHatPlugin): + self.add_copy_spec("/sybase/%s/ASE*/%s.cfg" % (sid, sid)) + + def setup(self): +- collect_list_instances() +- collect_list_dbs() ++ self.collect_list_instances() ++ self.collect_list_dbs() + + # run sapconf in check mode + self.add_cmd_output("sapconf -n", +-- +1.8.3.1 + diff --git a/sos-sat6-capsule-debug.patch b/sos-sat6-capsule-debug.patch new file mode 100644 index 0000000..470eb29 --- /dev/null +++ b/sos-sat6-capsule-debug.patch @@ -0,0 +1,92 @@ +From 5cc06136d68536b806ce09ce61f800d9a7938790 Mon Sep 17 00:00:00 2001 +From: Lukas Zapletal +Date: Tue, 3 Feb 2015 16:42:11 +0100 +Subject: [PATCH] [foreman] Skip collection of generic resources + +New option was added to foreman-debug (-g) to skip collecting of generic +resources (firewall, selinux, cpu, memory). This patch leverages that. + +https://github.com/theforeman/foreman/blob/develop/script/foreman-debug + +Since katello-debug is now part of foreman-debug (as a plugin), there is no +need of separate sosreport plugin. + +https://github.com/Katello/katello/blob/master/deploy/script/katello-debug.sh + +New subpackage called foreman-debug was introduced. It is present in both +upstream Foreman and Katello installations as well as on both Satellite 6 main +node and capsule instances. It can be used to detect if foreman-debug script is +present. + +Signed-off-by: Lukas Zapletal +--- + sos/plugins/foreman.py | 6 +++--- + sos/plugins/katello.py | 32 -------------------------------- + 2 files changed, 3 insertions(+), 35 deletions(-) + delete mode 100644 sos/plugins/katello.py + +diff --git a/sos/plugins/foreman.py b/sos/plugins/foreman.py +index 896add1..e50cbdf 100644 +--- a/sos/plugins/foreman.py ++++ b/sos/plugins/foreman.py +@@ -18,16 +18,16 @@ from sos.plugins import Plugin, RedHatPlugin + + + class Foreman(Plugin, RedHatPlugin): +- """Foreman systems management ++ """Foreman/Satellite 6 systems management + """ + + plugin_name = 'foreman' + profiles = ('sysmgmt',) +- packages = ('foreman') ++ packages = ('foreman-debug') + + def setup(self): + cmd = "foreman-debug" + path = self.get_cmd_output_path(name="foreman-debug") +- self.add_cmd_output("%s -q -a -d %s" % (cmd, path)) ++ self.add_cmd_output("%s -g -q -a -d %s" % (cmd, path)) + + # vim: et ts=4 sw=4 +diff --git a/sos/plugins/katello.py b/sos/plugins/katello.py +deleted file mode 100644 +index 795c07e..0000000 +--- a/sos/plugins/katello.py ++++ /dev/null +@@ -1,32 +0,0 @@ +-# Copyright (C) 2013 Red Hat, Inc., Lukas Zapletal +- +-# 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 Katello(Plugin, RedHatPlugin): +- """Katello systems management +- """ +- +- plugin_name = 'katello' +- profiles = ('sysmgmt',) +- packages = ('katello', 'katello-common', 'katello-headpin') +- +- def setup(self): +- self.add_cmd_output("katello-debug --notar -d %s" +- % self.get_cmd_output_path(name="katello-debug")) +- +-# vim: et ts=4 sw=4 +-- +1.8.3.1 + diff --git a/sos-services-add-more-diagnostics.patch b/sos-services-add-more-diagnostics.patch new file mode 100644 index 0000000..19d8166 --- /dev/null +++ b/sos-services-add-more-diagnostics.patch @@ -0,0 +1,479 @@ +From b502b9f51b4d314ed6fa76d66a6db8aea7d32c12 Mon Sep 17 00:00:00 2001 +From: Pavel Moravec +Date: Sun, 31 May 2015 16:00:16 +0200 +Subject: [PATCH 1/8] [startup] rename plugin to 'services' + +The plugin is supposed to collect information about services +rather than about their startup. + +Signed-off-by: Pavel Moravec +--- + sos/plugins/services.py | 56 +++++++++++++++++++++++++++++++++++++++++++++++++ + sos/plugins/startup.py | 56 ------------------------------------------------- + 2 files changed, 56 insertions(+), 56 deletions(-) + create mode 100644 sos/plugins/services.py + delete mode 100644 sos/plugins/startup.py + +diff --git a/sos/plugins/services.py b/sos/plugins/services.py +new file mode 100644 +index 0000000..606a135 +--- /dev/null ++++ b/sos/plugins/services.py +@@ -0,0 +1,56 @@ ++# 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") ++ ++ ++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: et ts=4 sw=4 +diff --git a/sos/plugins/startup.py b/sos/plugins/startup.py +deleted file mode 100644 +index 9d92370..0000000 +--- a/sos/plugins/startup.py ++++ /dev/null +@@ -1,56 +0,0 @@ +-# 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 Startup(Plugin): +- """System startup +- """ +- +- plugin_name = "startup" +- 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") +- +- +-class RedHatStartup(Startup, RedHatPlugin): +- +- def setup(self): +- super(RedHatStartup, self).setup() +- self.add_cmd_output("/sbin/chkconfig --list", root_symlink="chkconfig") +- +- +-class DebianStartup(Startup, DebianPlugin, UbuntuPlugin): +- +- def setup(self): +- super(DebianStartup, 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: et ts=4 sw=4 +-- +1.8.3.1 + + +From 5204d62fdb362fb5cc4a897c90faa9539715fc74 Mon Sep 17 00:00:00 2001 +From: Pavel Moravec +Date: Tue, 7 Jul 2015 13:03:14 +0200 +Subject: [PATCH 2/8] [services] add "ls /var/lock/subsys" + +Signed-off-by: Pavel Moravec +--- + sos/plugins/services.py | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/sos/plugins/services.py b/sos/plugins/services.py +index 606a135..ab9f8ce 100644 +--- a/sos/plugins/services.py ++++ b/sos/plugins/services.py +@@ -32,7 +32,10 @@ class Services(Plugin): + ]) + if self.get_option('servicestatus'): + self.add_cmd_output("/sbin/service --status-all") +- self.add_cmd_output("/sbin/runlevel") ++ self.add_cmd_output([ ++ "/sbin/runlevel", ++ "ls /var/lock/subsys" ++ ]) + + + class RedHatServices(Services, RedHatPlugin): +-- +1.8.3.1 + + +From e00447e7ee346aa3be685a91ebba7cf208c4f205 Mon Sep 17 00:00:00 2001 +From: Pavel Moravec +Date: Sun, 31 May 2015 16:04:19 +0200 +Subject: [PATCH 3/8] [ntp] Collect "ntpq -p" output + +Partially solves #570 + +Signed-off-by: Pavel Moravec +--- + sos/plugins/ntp.py | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/sos/plugins/ntp.py b/sos/plugins/ntp.py +index 0e39b9d..c0f731d 100644 +--- a/sos/plugins/ntp.py ++++ b/sos/plugins/ntp.py +@@ -30,7 +30,10 @@ class Ntp(Plugin): + "/etc/ntp/step-tickers", + "/etc/ntp/ntpservers" + ]) +- self.add_cmd_output("ntptime") ++ self.add_cmd_output([ ++ "ntptime", ++ "ntpq -p" ++ ]) + + + class RedHatNtp(Ntp, RedHatPlugin): +-- +1.8.3.1 + + +From 83ef3aff955a33bb58c578479ac6b63a615b4521 Mon Sep 17 00:00:00 2001 +From: Pavel Moravec +Date: Sun, 31 May 2015 16:07:06 +0200 +Subject: [PATCH 4/8] [networking] Collect "ethtool -T $NIC" + +Partially solves #570 + +Signed-off-by: Pavel Moravec +--- + sos/plugins/networking.py | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sos/plugins/networking.py b/sos/plugins/networking.py +index f2b06a6..b2c74c1 100644 +--- a/sos/plugins/networking.py ++++ b/sos/plugins/networking.py +@@ -184,6 +184,7 @@ class Networking(Plugin): + "ethtool -i "+eth, + "ethtool -k "+eth, + "ethtool -S "+eth, ++ "ethtool -T "+eth, + "ethtool -a "+eth, + "ethtool -c "+eth, + "ethtool -g "+eth +-- +1.8.3.1 + + +From 002cef3eddc288352d0b92f6272fbd2e85280e6e Mon Sep 17 00:00:00 2001 +From: Pavel Moravec +Date: Sun, 31 May 2015 16:17:40 +0200 +Subject: [PATCH 5/8] [ptp] Add new plugin for Precision time protocol + +Partially resolves #570 + +Signed-off-by: Pavel Moravec +--- + sos/plugins/ptp.py | 36 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + create mode 100644 sos/plugins/ptp.py + +diff --git a/sos/plugins/ptp.py b/sos/plugins/ptp.py +new file mode 100644 +index 0000000..a6ac648 +--- /dev/null ++++ b/sos/plugins/ptp.py +@@ -0,0 +1,36 @@ ++# Copyright (C) 2015 Pavel Moravec ++ ++# 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 Ptp(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin): ++ """Precision time protocol ++ """ ++ ++ plugin_name = "ptp" ++ profiles = ('system', 'services') ++ ++ packages = ('linuxptp',) ++ ++ def setup(self): ++ self.add_copy_spec([ ++ "/etc/ptp4l.conf", ++ "/etc/timemaster.conf", ++ "/sys/class/ptp" ++ ]) ++ ++# vim: et ts=4 sw=4 +-- +1.8.3.1 + + +From 72e2e32eaa97c6c76b61635dd0fafeb4dcc1aa7d Mon Sep 17 00:00:00 2001 +From: Pavel Moravec +Date: Sun, 31 May 2015 16:19:29 +0200 +Subject: [PATCH 6/8] [process] Collect few "ps" outputs + +Partially solves $570 + +Signed-off-by: Pavel Moravec +(edits for readability & line length) +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/process.py | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/sos/plugins/process.py b/sos/plugins/process.py +index 6ae189b..a643844 100644 +--- a/sos/plugins/process.py ++++ b/sos/plugins/process.py +@@ -23,13 +23,20 @@ class Process(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin): + 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" ++ "ps alxwww", ++ "%s %s" % (ps_axo, ps_group_opts), ++ "%s %s" % (ps_axo, ps_sched_opts) + ]) + + # vim: et ts=4 sw=4 +-- +1.8.3.1 + + +From 0b9a4c545582ed73f89ee4a7572ecb631633819e Mon Sep 17 00:00:00 2001 +From: Pavel Moravec +Date: Sun, 31 May 2015 16:21:28 +0200 +Subject: [PATCH 7/8] [sysvipc] Collect "ipcs -u" + +Partially solves #570 + +Signed-off-by: Pavel Moravec +--- + sos/plugins/sysvipc.py | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/sos/plugins/sysvipc.py b/sos/plugins/sysvipc.py +index a0732e7..a98abf9 100644 +--- a/sos/plugins/sysvipc.py ++++ b/sos/plugins/sysvipc.py +@@ -29,6 +29,9 @@ class SysVIPC(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin): + "/proc/sysvipc/sem", + "/proc/sysvipc/shm" + ]) +- self.add_cmd_output("ipcs") ++ self.add_cmd_output([ ++ "ipcs", ++ "ipcs -u" ++ ]) + + # vim: et ts=4 sw=4 +-- +1.8.3.1 + + +From fb7bbcf9e60002d75db383fac08244a7fa06a1d6 Mon Sep 17 00:00:00 2001 +From: Pavel Moravec +Date: Sun, 31 May 2015 16:24:23 +0200 +Subject: [PATCH 8/8] [devices] New plugin to collect "udevadm info + --export-db" + +Partially resolves #570 + +Signed-off-by: Pavel Moravec +--- + sos/plugins/devices.py | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + create mode 100644 sos/plugins/devices.py + +diff --git a/sos/plugins/devices.py b/sos/plugins/devices.py +new file mode 100644 +index 0000000..5e0283a +--- /dev/null ++++ b/sos/plugins/devices.py +@@ -0,0 +1,28 @@ ++# 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 +-- +1.8.3.1 + +From c05fa2947937a5adc3496c4e66b649633de054e9 Mon Sep 17 00:00:00 2001 +From: Alexandru Juncu +Date: Tue, 24 Feb 2015 18:28:04 +0100 +Subject: [PATCH] [last] information about login actions + +This is useful information to be correlated with shutdown/reboot +events in /var/log/messages to identify graceful shutdowns/reboots +and lower false positives about system crashes. + +Resolves #572. + +Signed-off-by: Alexandru Juncu +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/last.py | 33 +++++++++++++++++++++++++++++++++ + 1 file changed, 33 insertions(+) + create mode 100644 sos/plugins/last.py + +diff --git a/sos/plugins/last.py b/sos/plugins/last.py +new file mode 100644 +index 0000000..d6b791d +--- /dev/null ++++ b/sos/plugins/last.py +@@ -0,0 +1,33 @@ ++# 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 Last(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin): ++ """login information ++ """ ++ ++ plugin_name = 'last' ++ profiles = ('system',) ++ ++ def setup(self): ++ self.add_cmd_output("last", root_symlink="last") ++ self.add_cmd_output([ ++ "last reboot", ++ "last shutdown", ++ "lastlog" ++ ]) ++ ++# vim: et ts=4 sw=4 +-- +1.8.3.1 + diff --git a/sos-six-compat.patch b/sos-six-compat.patch new file mode 100644 index 0000000..576b77c --- /dev/null +++ b/sos-six-compat.patch @@ -0,0 +1,63 @@ +From b61a193b98b896164a8caefa088bb09297f1e3ca Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Wed, 1 Oct 2014 17:08:50 +0100 +Subject: [PATCH 1/2] [utilities] invert sense of six.PY2 test + +Old versions of six do not include a 'PY2' attribute leading to +an exception in sos_get_command_output(). Invert the sense of the +test and check that six.PY3 is false instead as all versions of +the module include this attribute. + +Signed-off-by: Bryn M. Reeves +--- + sos/utilities.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sos/utilities.py b/sos/utilities.py +index 7c06781..7e8cd7e 100644 +--- a/sos/utilities.py ++++ b/sos/utilities.py +@@ -139,7 +139,7 @@ def sos_get_command_output(command, timeout=300, runat=None): + command = "timeout %ds %s" % (timeout, command) + + # shlex.split() reacts badly to unicode on older python runtimes. +- if six.PY2: ++ if not six.PY3: + command = command.encode('utf-8') + args = shlex.split(command) + try: +-- +1.9.3 + + +From f9c811abc07f1e3044b1dbf29fdd5cd1f68812bc Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Wed, 1 Oct 2014 17:34:56 +0100 +Subject: [PATCH 2/2] [archive] invert sense of six.PY2 test + +Old versions of six do not include a 'PY2' attribute leading to +an exception in sos_get_command_output(). Invert the sense of the +test and check that six.PY3 is false instead as all versions of +the module include this attribute. + +Signed-off-by: Bryn M. Reeves +--- + sos/archive.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sos/archive.py b/sos/archive.py +index 245f904..2e42bbd 100644 +--- a/sos/archive.py ++++ b/sos/archive.py +@@ -357,7 +357,7 @@ class TarFileArchive(FileCacheArchive): + + def _build_archive(self): + # python2.6 TarFile lacks the filter parameter +- if six.PY2 and sys.version_info[1] < 7: ++ 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") +-- +1.9.3 + diff --git a/sos-sos-inside-container.patch b/sos-sos-inside-container.patch new file mode 100644 index 0000000..213a75b --- /dev/null +++ b/sos-sos-inside-container.patch @@ -0,0 +1,2458 @@ +From cb3d265849771f7e53b0587196930328005414e0 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Mon, 19 Jan 2015 18:54:09 +0000 +Subject: [PATCH 01/38] [sosreport] add --sysroot option + +Add a --sysroot=SYSROOT option to specify that the root file system to +be inspected is mounted at SYSROOT. + +This allows basic support for container environments where sos is +running in a container and inspecting the containing host and its +environment ('superspection'). + +For this to work currently the following conditions must be met: + +- sos is sufficiently privileged to read and search relevant file + system paths within SYSROOT + +- sos must share the PID and network namespace of the target host + +- binaries called by sos must be present and executable in the + SYSROOT inherited by sos. If PATH includes paths inside SYSROOT + appropriate values must be set for LD_LIBRARY_PATH to allow + shared executables to be linked. + +Signed-off-by: Bryn M. Reeves +--- + sos/sosreport.py | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +diff --git a/sos/sosreport.py b/sos/sosreport.py +index 9a0cf6c..47eddc9 100644 +--- a/sos/sosreport.py ++++ b/sos/sosreport.py +@@ -529,6 +529,17 @@ class SoSOptions(object): + self._report = value + + @property ++ def sysroot(self): ++ if self._options is not None: ++ return self._options.sysroot ++ return self._sysroot ++ ++ @sysroot.setter ++ def sysroot(self, value): ++ self._check_options_initialized() ++ self._sysroot = value ++ ++ @property + def compression_type(self): + if self._options is not None: + return self._options.compression_type +@@ -615,6 +626,9 @@ class SoSOptions(object): + parser.add_option("--no-report", action="store_true", + dest="report", + help="Disable HTML/XML reporting", default=False) ++ parser.add_option("-s", "--sysroot", action="store", dest="sysroot", ++ help="system root directory path (default='/')", ++ default="/") + parser.add_option("-z", "--compression-type", dest="compression_type", + help="compression technology to use [auto, " + "gzip, bzip2, xz] (default=auto)", +-- +1.8.3.1 + + +From 3eed62e132f67930bb1cf5c9eaa5927083011043 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Fri, 23 Jan 2015 15:24:00 +0000 +Subject: [PATCH 02/38] [plugins] propagate sysroot to Plugin via commons + +Although plugins should generally be unaware that they are being +run with an alternate sysroot the generic plugin IO code must +peform the appropriate path prefixing when sysroot is not '/'. + +Propagate sysroot to plugin classes via the commons dictionary. + +Signed-off-by: Bryn M. Reeves +--- + sos/sosreport.py | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/sos/sosreport.py b/sos/sosreport.py +index 47eddc9..580b5bd 100644 +--- a/sos/sosreport.py ++++ b/sos/sosreport.py +@@ -651,6 +651,7 @@ class SoSReport(object): + self.archive = None + self.tempfile_util = None + self._args = args ++ self.sysroot = "/" + + try: + import signal +@@ -681,6 +682,10 @@ class SoSReport(object): + self.tempfile_util = TempFileUtil(self.tmpdir) + self._set_directories() + ++ # set alternate system root directory ++ if self.opts.sysroot: ++ self.sysroot = self.opts.sysroot ++ + def print_header(self): + self.ui_log.info("\n%s\n" % _("sosreport (version %s)" % + (__version__,))) +@@ -693,6 +698,7 @@ class SoSReport(object): + 'tmpdir': self.tmpdir, + 'soslog': self.soslog, + 'policy': self.policy, ++ 'sysroot': self.sysroot, + 'verbosity': self.opts.verbosity, + 'xmlreport': self.xml_report, + 'cmdlineopts': self.opts, +-- +1.8.3.1 + + +From b1f3b3373e8ef3e94238760a3e7e78d95c564260 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Fri, 23 Jan 2015 23:17:34 +0000 +Subject: [PATCH 03/38] [plugins] prefix target paths with self.sysroot + +Prefix copyspecs with self.sysroot when using an alternate root +path. Prefixes are applied before expanding copyspecs and the +prefixed paths are stored as the 'srcpath' attribute in the +archive. Destination paths in the report archive do not include +the prefix. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/__init__.py | 50 +++++++++++++++++++++++++++++++++++-------- + tests/option_tests.py | 3 ++- + tests/plugin_tests.py | 57 ++++++++++++++++++++++++++++++++----------------- + 3 files changed, 81 insertions(+), 29 deletions(-) + +diff --git a/sos/plugins/__init__.py b/sos/plugins/__init__.py +index 413ee73..790338b 100644 +--- a/sos/plugins/__init__.py ++++ b/sos/plugins/__init__.py +@@ -101,6 +101,7 @@ class Plugin(object): + files = () + archive = None + profiles = () ++ sysroot = '/' + + def __init__(self, commons): + if not getattr(self, "option_list", False): +@@ -117,6 +118,7 @@ class Plugin(object): + 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') +@@ -154,6 +156,19 @@ class Plugin(object): + 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 path.startswith(self.sysroot): ++ return path[len(self.sysroot):] ++ return path ++ ++ def use_sysroot(self): ++ return self.sysroot != os.path.abspath(os.sep) ++ + def is_installed(self, package_name): + '''Is the package $package_name installed?''' + return self.policy().pkg_by_name(package_name) is not None +@@ -207,6 +222,7 @@ class Plugin(object): + ''' + 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: +@@ -257,8 +273,9 @@ class Plugin(object): + 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, srcpath) ++ self.archive.add_link(reldest, dstpath) + + if os.path.isdir(absdest): + self._log_debug("link '%s' is a directory, skipping..." % linkdest) +@@ -277,7 +294,7 @@ class Plugin(object): + self._do_copy_path(absdest) + + self.copied_files.append({'srcpath': srcpath, +- 'dstpath': srcpath, ++ 'dstpath': dstpath, + 'symlink': "yes", + 'pointsto': linkdest}) + +@@ -288,6 +305,8 @@ class Plugin(object): + self._do_copy_path(os.path.join(srcpath, afile), dest=None) + + 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"] +@@ -315,6 +334,9 @@ class Plugin(object): + if not dest: + dest = srcpath + ++ if self.use_sysroot(): ++ dest = self.strip_sysroot(dest) ++ + try: + st = os.lstat(srcpath) + except (OSError, IOError): +@@ -333,7 +355,7 @@ class Plugin(object): + 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, srcpath)) ++ % (ntype, dest)) + self._copy_node(srcpath, st) + return + +@@ -347,9 +369,11 @@ class Plugin(object): + else: + self.archive.add_file(srcpath, dest) + +- self.copied_files.append({'srcpath': srcpath, +- 'dstpath': dest, +- 'symlink': "no"}) ++ self.copied_files.append({ ++ 'srcpath': srcpath, ++ 'dstpath': dest, ++ 'symlink': "no" ++ }) + + def add_forbidden_path(self, forbiddenPath): + """Specify a path to not copy, even if it's part of a copy_specs[] +@@ -416,6 +440,9 @@ class Plugin(object): + 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 +@@ -424,10 +451,13 @@ class Plugin(object): + 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 +@@ -438,7 +468,7 @@ class Plugin(object): + if sizelimit and current_size > sizelimit: + limit_reached = True + break +- self.add_copy_spec(_file) ++ self._add_copy_paths([_file]) + + if limit_reached and tailit: + file_name = _file +@@ -459,12 +489,14 @@ class Plugin(object): + 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.copy_paths.update(copy_paths) +- self._log_info("added copyspec '%s'" % copyspec) ++ self._add_copy_paths(copy_paths) ++ self._log_info("added copyspec '%s'" % copy_paths) + + def get_command_output(self, prog, timeout=300, runat=None, stderr=True): + result = sos_get_command_output(prog, timeout=timeout, runat=runat, +diff --git a/tests/option_tests.py b/tests/option_tests.py +index fe37ccf..e8a26e2 100644 +--- a/tests/option_tests.py ++++ b/tests/option_tests.py +@@ -8,10 +8,11 @@ class GlobalOptionTest(unittest.TestCase): + + def setUp(self): + self.commons = { ++ 'sysroot': '/', + 'global_plugin_options': { + 'test_option': 'foobar', + 'baz': None, +- 'empty_global': True, ++ 'empty_global': True + }, + } + self.plugin = Plugin(self.commons) +diff --git a/tests/plugin_tests.py b/tests/plugin_tests.py +index e30ded5..14d3b49 100644 +--- a/tests/plugin_tests.py ++++ b/tests/plugin_tests.py +@@ -127,50 +127,53 @@ class PluginToolTests(unittest.TestCase): + + class PluginTests(unittest.TestCase): + ++ sysroot = os.getcwd() ++ + def setUp(self): + self.mp = MockPlugin({ +- 'cmdlineopts': MockOptions() ++ 'cmdlineopts': MockOptions(), ++ 'sysroot': self.sysroot + }) + self.mp.archive = MockArchive() + + def test_plugin_default_name(self): +- p = MockPlugin({}) ++ p = MockPlugin({'sysroot': self.sysroot}) + self.assertEquals(p.name(), "mockplugin") + + def test_plugin_set_name(self): +- p = NamedMockPlugin({}) ++ p = NamedMockPlugin({'sysroot': self.sysroot}) + self.assertEquals(p.name(), "testing") + + def test_plugin_no_descrip(self): +- p = MockPlugin({}) ++ p = MockPlugin({'sysroot': self.sysroot}) + self.assertEquals(p.get_description(), "") + + def test_plugin_no_descrip(self): +- p = NamedMockPlugin({}) ++ p = NamedMockPlugin({'sysroot': self.sysroot}) + self.assertEquals(p.get_description(), "This plugin has a description.") + + def test_set_plugin_option(self): +- p = MockPlugin({}) ++ p = MockPlugin({'sysroot': self.sysroot}) + p.set_option("opt", "testing") + self.assertEquals(p.get_option("opt"), "testing") + + def test_set_nonexistant_plugin_option(self): +- p = MockPlugin({}) ++ p = MockPlugin({'sysroot': self.sysroot}) + self.assertFalse(p.set_option("badopt", "testing")) + + def test_get_nonexistant_plugin_option(self): +- p = MockPlugin({}) ++ p = MockPlugin({'sysroot': self.sysroot}) + self.assertEquals(p.get_option("badopt"), 0) + + def test_get_unset_plugin_option(self): +- p = MockPlugin({}) ++ p = MockPlugin({'sysroot': self.sysroot}) + self.assertEquals(p.get_option("opt"), 0) + + def test_get_unset_plugin_option_with_default(self): + # this shows that even when we pass in a default to get, + # we'll get the option's default as set in the plugin + # this might not be what we really want +- p = MockPlugin({}) ++ p = MockPlugin({'sysroot': self.sysroot}) + self.assertEquals(p.get_option("opt", True), True) + + def test_get_unset_plugin_option_with_default_not_none(self): +@@ -178,20 +181,20 @@ class PluginTests(unittest.TestCase): + # if the plugin default is not None + # we'll get the option's default as set in the plugin + # this might not be what we really want +- p = MockPlugin({}) ++ p = MockPlugin({'sysroot': self.sysroot}) + self.assertEquals(p.get_option("opt2", True), False) + + def test_get_option_as_list_plugin_option(self): +- p = MockPlugin({}) ++ p = MockPlugin({'sysroot': self.sysroot}) + p.set_option("opt", "one,two,three") + self.assertEquals(p.get_option_as_list("opt"), ['one', 'two', 'three']) + + def test_get_option_as_list_plugin_option_default(self): +- p = MockPlugin({}) ++ p = MockPlugin({'sysroot': self.sysroot}) + self.assertEquals(p.get_option_as_list("opt", default=[]), []) + + def test_get_option_as_list_plugin_option_not_list(self): +- p = MockPlugin({}) ++ p = MockPlugin({'sysroot': self.sysroot}) + p.set_option("opt", "testing") + self.assertEquals(p.get_option_as_list("opt"), ['testing']) + +@@ -205,7 +208,8 @@ class PluginTests(unittest.TestCase): + + def test_copy_dir_forbidden_path(self): + p = ForbiddenMockPlugin({ +- 'cmdlineopts': MockOptions() ++ 'cmdlineopts': MockOptions(), ++ 'sysroot': self.sysroot + }) + p.archive = MockArchive() + p.setup() +@@ -219,12 +223,18 @@ class AddCopySpecTests(unittest.TestCase): + + def setUp(self): + self.mp = MockPlugin({ +- 'cmdlineopts': MockOptions() ++ 'cmdlineopts': MockOptions(), ++ 'sysroot': os.getcwd() + }) + self.mp.archive = MockArchive() + + def assert_expect_paths(self): +- self.assertEquals(self.mp.copy_paths, self.expect_paths) ++ def pathmunge(path): ++ if path[0] == '/': ++ path = path[1:] ++ return os.path.join(self.mp.sysroot, path) ++ expected_paths = set(map(pathmunge, self.expect_paths)) ++ self.assertEquals(self.mp.copy_paths, expected_paths) + + # add_copy_spec() + +@@ -242,6 +252,7 @@ class AddCopySpecTests(unittest.TestCase): + # add_copy_spec_limit() + + def test_single_file_over_limit(self): ++ self.mp.sysroot = '/' + fn = create_file(2) # create 2MB file, consider a context manager + self.mp.add_copy_spec_limit(fn, 1) + content, fname = self.mp.copy_strings[0] +@@ -252,10 +263,12 @@ class AddCopySpecTests(unittest.TestCase): + os.unlink(fn) + + def test_bad_filename(self): ++ self.mp.sysroot = '/' + self.assertFalse(self.mp.add_copy_spec_limit('', 1)) + self.assertFalse(self.mp.add_copy_spec_limit(None, 1)) + + def test_glob_file_over_limit(self): ++ self.mp.sysroot = '/' + # assume these are in /tmp + fn = create_file(2) + fn2 = create_file(2) +@@ -271,7 +284,10 @@ class AddCopySpecTests(unittest.TestCase): + class CheckEnabledTests(unittest.TestCase): + + def setUp(self): +- self.mp = EnablerPlugin({'policy': sos.policies.load()}) ++ self.mp = EnablerPlugin({ ++ 'policy': sos.policies.load(), ++ 'sysroot': os.getcwd() ++ }) + + def test_checks_for_file(self): + f = j("tail_test.txt") +@@ -296,7 +312,8 @@ class RegexSubTests(unittest.TestCase): + + def setUp(self): + self.mp = MockPlugin({ +- 'cmdlineopts': MockOptions() ++ 'cmdlineopts': MockOptions(), ++ 'sysroot': os.getcwd() + }) + self.mp.archive = MockArchive() + +@@ -310,6 +327,8 @@ class RegexSubTests(unittest.TestCase): + self.assertEquals(0, replacements) + + def test_replacements(self): ++ # test uses absolute paths ++ self.mp.sysroot = '/' + self.mp.add_copy_spec(j("tail_test.txt")) + self.mp.collect() + replacements = self.mp.do_file_sub(j("tail_test.txt"), r"(tail)", "foobar") +-- +1.8.3.1 + + +From c4957d8aa4ea35f879639726267043f6bb46cc7c Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Sat, 24 Jan 2015 00:35:09 +0000 +Subject: [PATCH 04/38] [docs] add -s/--sysroot to sosreport.1 + +Signed-off-by: Bryn M. Reeves +--- + man/en/sosreport.1 | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/man/en/sosreport.1 b/man/en/sosreport.1 +index c2b60d8..b0a86f2 100644 +--- a/man/en/sosreport.1 ++++ b/man/en/sosreport.1 +@@ -12,6 +12,7 @@ sosreport \- Collect and package diagnostic and support data + [--no-report] [--config-file conf]\fR + [--batch] [--build] [--debug]\fR + [--name name] [--case-id id] [--ticket-number nr] ++ [-s|--sysroot]\fR + [--tmp-dir directory]\fR + [-p|--profile profile-name]\fR + [--list-profiles]\fR +@@ -72,6 +73,10 @@ Disable HTML/XML report writing. + .B \--config-file CONFIG + Specify alternate configuration file. + .TP ++.B \-s, \--sysroot SYSROOT ++Specify an alternate root file system path. Useful for collecting ++reports from containers and images. ++.TP + .B \--tmp-dir DIRECTORY + Specify alternate temporary directory to copy data as well as the + compressed report. +-- +1.8.3.1 + + +From 4a0a3f9607006d402713320fc31780fb54556e6a Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Sun, 25 Jan 2015 14:20:10 +0000 +Subject: [PATCH 05/38] [utilities] add chroot support to + sos_get_command_output() + +Allow callers of sos_get_command_output() to specify a path to +chroot into before executing command. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/__init__.py | 2 +- + sos/utilities.py | 27 ++++++++++++++++----------- + tests/utilities_tests.py | 5 +++++ + 3 files changed, 22 insertions(+), 12 deletions(-) + +diff --git a/sos/plugins/__init__.py b/sos/plugins/__init__.py +index 790338b..137e1a1 100644 +--- a/sos/plugins/__init__.py ++++ b/sos/plugins/__init__.py +@@ -499,7 +499,7 @@ class Plugin(object): + self._log_info("added copyspec '%s'" % copy_paths) + + def get_command_output(self, prog, timeout=300, runat=None, stderr=True): +- result = sos_get_command_output(prog, timeout=timeout, runat=runat, ++ result = sos_get_command_output(prog, timeout=timeout, chdir=runat, + stderr=stderr) + if result['status'] == 124: + self._log_warn("command '%s' timed out after %ds" +diff --git a/sos/utilities.py b/sos/utilities.py +index dfe6128..a82ac7c 100644 +--- a/sos/utilities.py ++++ b/sos/utilities.py +@@ -120,15 +120,20 @@ def is_executable(command): + return any(os.access(path, os.X_OK) for path in candidates) + + +-def sos_get_command_output(command, timeout=300, runat=None, stderr=True): +- """Execute a command through the system shell. First checks to see if the +- requested command is executable. Returns (returncode, stdout, 0)""" +- def _child_chdir(): +- if(runat): +- try: +- os.chdir(runat) +- except: +- self.log_error("failed to chdir to '%s'" % runat) ++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 +@@ -145,7 +150,7 @@ def sos_get_command_output(command, timeout=300, runat=None, stderr=True): + p = Popen(args, shell=False, stdout=PIPE, + stderr=STDOUT if stderr else PIPE, + bufsize=-1, env=cmd_env, close_fds=True, +- preexec_fn=_child_chdir) ++ preexec_fn=_child_prep_fn) + except OSError as e: + if e.errno == errno.ENOENT: + return {'status': 127, 'output': ""} +@@ -185,7 +190,7 @@ def shell_out(cmd, timeout=30, 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, runat=runat)['output'] ++ return sos_get_command_output(cmd, timeout=timeout, chdir=runat)['output'] + + + class ImporterHelper(object): +diff --git a/tests/utilities_tests.py b/tests/utilities_tests.py +index 607056e..9327b1f 100644 +--- a/tests/utilities_tests.py ++++ b/tests/utilities_tests.py +@@ -68,6 +68,11 @@ class ExecutableTest(unittest.TestCase): + self.assertEquals(result['status'], 127) + self.assertEquals(result['output'], "") + ++ def test_output_chdir(self): ++ result = sos_get_command_output("/usr/bin/pwd", chdir=TEST_DIR) ++ self.assertEquals(result['status'], 0) ++ self.assertEquals(result['output'].strip(), TEST_DIR) ++ + def test_shell_out(self): + path = os.path.join(TEST_DIR, 'test_exe.py') + self.assertEquals("executed\n", shell_out(path)) +-- +1.8.3.1 + + +From 9a87cb3415a7a9587828ee40d689439949def1be Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Sun, 25 Jan 2015 14:30:13 +0000 +Subject: [PATCH 06/38] [sosreport] add --chroot option + +Add a --chroot option to sosreport to control command chrooting. + +The option takes one of three values: + + * auto - Allow callers of the API to control chroot behaviour + * always - Always chroot external commands to --sysroot + * never - Never chroot external commands + +This is a fairly low-level option and may not be exposed to the +user in a final release; for now it will allow tests in container +environments to control the chrooting behaviour used for a run. + +Signed-off-by: Bryn M. Reeves +--- + sos/sosreport.py | 19 +++++++++++++++++++ + tests/utilities_tests.py | 4 +++- + 2 files changed, 22 insertions(+), 1 deletion(-) + +diff --git a/sos/sosreport.py b/sos/sosreport.py +index 580b5bd..d9abcb8 100644 +--- a/sos/sosreport.py ++++ b/sos/sosreport.py +@@ -540,6 +540,21 @@ class SoSOptions(object): + self._sysroot = value + + @property ++ def chroot(self): ++ if self._options is not None: ++ return self._options.chroot ++ return self._chroot ++ ++ @chroot.setter ++ def chroot(self, value): ++ self._check_options_initialized() ++ if value not in ["auto", "always", "never"]: ++ msg = "SoSOptions.chroot '%s' is not a valid chroot mode: " ++ msg += "('auto', 'always', 'never')" ++ raise ValueError(msg % value) ++ self._chroot = value ++ ++ @property + def compression_type(self): + if self._options is not None: + return self._options.compression_type +@@ -630,6 +645,10 @@ class SoSOptions(object): + parser.add_option("-s", "--sysroot", action="store", dest="sysroot", + help="system root directory path (default='/')", + default="/") ++ parser.add_option("-c", "--chroot", action="store", dest="chroot", ++ help="chroot executed commands to SYSROOT " ++ "[auto, always, never] (default=auto)", ++ default="auto") + parser.add_option("-z", "--compression-type", dest="compression_type", + help="compression technology to use [auto, " + "gzip, bzip2, xz] (default=auto)", +diff --git a/tests/utilities_tests.py b/tests/utilities_tests.py +index 9327b1f..c464692 100644 +--- a/tests/utilities_tests.py ++++ b/tests/utilities_tests.py +@@ -69,7 +69,9 @@ class ExecutableTest(unittest.TestCase): + self.assertEquals(result['output'], "") + + def test_output_chdir(self): +- result = sos_get_command_output("/usr/bin/pwd", chdir=TEST_DIR) ++ cmd = "/bin/bash -c 'echo $PWD'" ++ result = sos_get_command_output(cmd, chdir=TEST_DIR) ++ print(result) + self.assertEquals(result['status'], 0) + self.assertEquals(result['output'].strip(), TEST_DIR) + +-- +1.8.3.1 + + +From 0d060dc3aa5e90373e7bb55f9310b4cf9db0dad4 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Sun, 25 Jan 2015 15:04:29 +0000 +Subject: [PATCH 07/38] [plugins] implement --chroot for command callouts + +When --chroot=always is given chroot all commands to SYSROOT. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/__init__.py | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/sos/plugins/__init__.py b/sos/plugins/__init__.py +index 137e1a1..10fdae5 100644 +--- a/sos/plugins/__init__.py ++++ b/sos/plugins/__init__.py +@@ -499,8 +499,12 @@ class Plugin(object): + self._log_info("added copyspec '%s'" % copy_paths) + + def get_command_output(self, prog, timeout=300, runat=None, stderr=True): +- result = sos_get_command_output(prog, timeout=timeout, chdir=runat, +- stderr=stderr) ++ if 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)) +-- +1.8.3.1 + + +From f6f7934c7d3e7f6cb41879fc0625b06d0468af4e Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Sun, 25 Jan 2015 19:32:04 +0000 +Subject: [PATCH 08/38] [plugin] fix chrooted symlink handling + +_copy_symlink() needs to strip_sysroot(), not join_sysroot(), on +a link target before handing it to _do_copy_path(). + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/__init__.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sos/plugins/__init__.py b/sos/plugins/__init__.py +index 10fdae5..9d04939 100644 +--- a/sos/plugins/__init__.py ++++ b/sos/plugins/__init__.py +@@ -294,7 +294,7 @@ class Plugin(object): + # to absolute paths to pass to _do_copy_path. + self._log_debug("normalized link target '%s' as '%s'" + % (linkdest, absdest)) +- self._do_copy_path(absdest) ++ self._do_copy_path(self.strip_sysroot(absdest)) + + self.copied_files.append({'srcpath': srcpath, + 'dstpath': dstpath, +-- +1.8.3.1 + + +From b16fbf3911c6256674e072cff6fa706050861993 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Sun, 25 Jan 2015 21:54:19 +0000 +Subject: [PATCH 09/38] [sosreport] check for valid CHROOT values + +Signed-off-by: Bryn M. Reeves +--- + sos/sosreport.py | 16 +++++++++++++--- + 1 file changed, 13 insertions(+), 3 deletions(-) + +diff --git a/sos/sosreport.py b/sos/sosreport.py +index d9abcb8..a0b89e7 100644 +--- a/sos/sosreport.py ++++ b/sos/sosreport.py +@@ -225,6 +225,10 @@ class XmlReport(object): + outf.close() + + ++# valid modes for --chroot ++chroot_modes = ["auto", "always", "never"] ++ ++ + class SoSOptions(object): + _list_plugins = False + _noplugins = [] +@@ -548,7 +552,7 @@ class SoSOptions(object): + @chroot.setter + def chroot(self, value): + self._check_options_initialized() +- if value not in ["auto", "always", "never"]: ++ if value not in chroot_modes: + msg = "SoSOptions.chroot '%s' is not a valid chroot mode: " + msg += "('auto', 'always', 'never')" + raise ValueError(msg % value) +@@ -705,6 +709,14 @@ class SoSReport(object): + if self.opts.sysroot: + self.sysroot = self.opts.sysroot + ++ self._setup_logging() ++ ++ if self.opts.chroot not in chroot_modes: ++ self.soslog.error("invalid chroot mode: %s" % self.opts.chroot) ++ logging.shutdown() ++ self.tempfile_util.clean() ++ self._exit(1) ++ + def print_header(self): + self.ui_log.info("\n%s\n" % _("sosreport (version %s)" % + (__version__,))) +@@ -1205,7 +1217,6 @@ class SoSReport(object): + self.ui_log.error(" %s while setting up plugins" + % e.strerror) + self.ui_log.error("") +- self._exit(1) + if self.raise_plugins: + raise + self._log_plugin_exception(plugname, "setup") +@@ -1455,7 +1466,6 @@ class SoSReport(object): + + def execute(self): + try: +- self._setup_logging() + self.policy.set_commons(self.get_commons()) + self.print_header() + self.load_plugins() +-- +1.8.3.1 + + +From f06efd6fa7bbb0c81ce0461d4eaeed225d6f04a2 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Sun, 25 Jan 2015 23:03:08 +0000 +Subject: [PATCH 10/38] [plugins] add chroot parameter to callout APIs + +Expose sos_get_command_output()'s chroot support to plugins via +add_cmd_output(), get_command_output(), call_ext_prog() and +related Plugin methods. + +'chroot' is a boolean indicating whether the command should run +in the chroot (True) or in the host namespace (False). + +Has no effect when Plugin.use_sysroot() is False. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/__init__.py | 50 ++++++++++++++++++++++++++++--------------------- + 1 file changed, 29 insertions(+), 21 deletions(-) + +diff --git a/sos/plugins/__init__.py b/sos/plugins/__init__.py +index 9d04939..c1b659d 100644 +--- a/sos/plugins/__init__.py ++++ b/sos/plugins/__init__.py +@@ -498,12 +498,13 @@ class Plugin(object): + self._add_copy_paths(copy_paths) + self._log_info("added copyspec '%s'" % copy_paths) + +- def get_command_output(self, prog, timeout=300, runat=None, stderr=True): +- if self.commons['cmdlineopts'].chroot == 'always': ++ 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 ++ 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" +@@ -513,12 +514,13 @@ class Plugin(object): + self._log_debug("could not run '%s': command not found" % prog) + return result + +- def call_ext_prog(self, prog, timeout=300, runat=None, stderr=True): ++ 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, runat=runat, +- stderr=True) ++ 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 +@@ -528,8 +530,8 @@ class Plugin(object): + return self.call_ext_prog(prog)['status'] == 0 + + def add_cmd_output(self, cmds, suggest_filename=None, +- root_symlink=None, timeout=300, runat=None, +- stderr=True): ++ 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] +@@ -537,9 +539,10 @@ class Plugin(object): + self._log_warn("ambiguous filename or symlink for command list") + for cmd in cmds: + cmdt = ( +- cmd, suggest_filename, root_symlink, timeout, runat, stderr ++ cmd, suggest_filename, root_symlink, timeout, stderr, ++ chroot, runat + ) +- _tuplefmt = "('%s', '%s', '%s', %s, '%s', '%s')" ++ _tuplefmt = "('%s', '%s', '%s', %s, '%s', '%s', '%s')" + _logstr = "packed command tuple: " + _tuplefmt + self._log_debug(_logstr % cmdt) + self.collect_cmds.append(cmdt) +@@ -594,14 +597,14 @@ class Plugin(object): + 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, +- runat=None, stderr=True): ++ 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, runat=runat, +- stderr=stderr) ++ 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 +@@ -650,15 +653,20 @@ class Plugin(object): + + def _collect_cmd_output(self): + for progs in zip(self.collect_cmds): +- (prog, suggest_filename, root_symlink, timeout, runat, stderr +- ) = progs[0] +- self._log_debug("unpacked command tuple: " +- + "('%s', '%s', '%s', %s, '%s', %s)" % progs[0]) ++ ( ++ 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, runat=runat, +- stderr=stderr) ++ root_symlink=root_symlink, timeout=timeout, ++ chroot=chroot, runat=runat) + + def _collect_strings(self): + for string, file_name in self.copy_strings: +-- +1.8.3.1 + + +From 3390d070b2945715a15f74462c511df2b2941ef5 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Sun, 25 Jan 2015 23:08:37 +0000 +Subject: [PATCH 11/38] [plugin] add tmp_in_sysroot() method + +Add a method that plugins can test to determine whether the +archive's temporary directory is inside sysroot. This is always +true when sysroot is '/'. When sysroot is a subdirectory of root +the temporary directory may be inaccessible from the chroot +namespace. Plugins can test this method to determine where to +write output. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/__init__.py | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/sos/plugins/__init__.py b/sos/plugins/__init__.py +index c1b659d..49f62bf 100644 +--- a/sos/plugins/__init__.py ++++ b/sos/plugins/__init__.py +@@ -169,6 +169,10 @@ class Plugin(object): + 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 +-- +1.8.3.1 + + +From 5ae1b392d1f081bcb43e91a572342d6f02e4728d Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Sun, 25 Jan 2015 23:27:51 +0000 +Subject: [PATCH 12/38] [plugin] enforce forbidden paths when --sysroot is set + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/__init__.py | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/sos/plugins/__init__.py b/sos/plugins/__init__.py +index 49f62bf..fd1acb5 100644 +--- a/sos/plugins/__init__.py ++++ b/sos/plugins/__init__.py +@@ -317,6 +317,8 @@ class Plugin(object): + 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): +@@ -379,13 +381,15 @@ class Plugin(object): + 'symlink': "no" + }) + +- def add_forbidden_path(self, forbiddenPath): ++ 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 filespec in glob.glob(forbiddenPath): +- self.forbidden_paths.append(filespec) ++ for path in glob.glob(forbidden): ++ self.forbidden_paths.append(path) + + def get_all_options(self): + """return a list of all options selected""" +-- +1.8.3.1 + + +From e18d25a0e0c10a2702893f7bae2530dc2a41a394 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Mon, 26 Jan 2015 00:00:08 +0000 +Subject: [PATCH 13/38] [cluster] handle crm_report with --sysroot + +Don't attempt to run crm_report in the chroot if tmp is not a +subdirectory of sysroot. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/cluster.py | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/sos/plugins/cluster.py b/sos/plugins/cluster.py +index ea5dbae..f52f154 100644 +--- a/sos/plugins/cluster.py ++++ b/sos/plugins/cluster.py +@@ -120,8 +120,9 @@ class Cluster(Plugin, RedHatPlugin): + 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)) ++ 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(): +-- +1.8.3.1 + + +From 2ca9c74454699ba6ecad21d6b0c0809333d729aa Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Mon, 26 Jan 2015 00:02:35 +0000 +Subject: [PATCH 14/38] [dmraid] don't chroot if tmp is not inside sysroot + +To dump metadata dmraid needs to chdir to the temporary archive +directory. Don't attempt to chroot into sysroot if the temporary +directory is not a subdirectory of it. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/dmraid.py | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/sos/plugins/dmraid.py b/sos/plugins/dmraid.py +index b7c0b42..87381a0 100644 +--- a/sos/plugins/dmraid.py ++++ b/sos/plugins/dmraid.py +@@ -39,6 +39,7 @@ class Dmraid(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin): + 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) ++ self.add_cmd_output("dmraid -rD", runat=metadata_path, ++ chroot=self.tmp_in_sysroot()) + + # vim: et ts=4 sw=4 +-- +1.8.3.1 + + +From 4ae09ee0ed25d771cc6cc8a013837ed4c647b3ed Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Mon, 26 Jan 2015 00:04:15 +0000 +Subject: [PATCH 15/38] [foreman] don't chroot if tmp is not inside sysroot + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/foreman.py | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/sos/plugins/foreman.py b/sos/plugins/foreman.py +index 9d1cbad..363b9d6 100644 +--- a/sos/plugins/foreman.py ++++ b/sos/plugins/foreman.py +@@ -27,7 +27,9 @@ class Foreman(Plugin, RedHatPlugin): + + def setup(self): + cmd = "foreman-debug" ++ + path = self.get_cmd_output_path(name="foreman-debug") +- self.add_cmd_output("%s -g -q -a -d %s" % (cmd, path)) ++ self.add_cmd_output("%s -g -q -a -d %s" % (cmd, path), ++ chroot=self.tmp_in_sysroot()) + + # vim: et ts=4 sw=4 +-- +1.8.3.1 + + +From 78761114ea9cc1b33233db2186a5ff762e1ac2f2 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Mon, 26 Jan 2015 00:07:12 +0000 +Subject: [PATCH 16/38] [libvirt] use join_sysroot() before calling + os.path.exists + +The libvirt plugin tests for the presence of files. Use +join_sysroot() to ensure the correct path is tested. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/libvirt.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sos/plugins/libvirt.py b/sos/plugins/libvirt.py +index aaf862b..295c8eb 100644 +--- a/sos/plugins/libvirt.py ++++ b/sos/plugins/libvirt.py +@@ -56,7 +56,7 @@ class Libvirt(Plugin, RedHatPlugin, UbuntuPlugin, DebianPlugin): + else: + self.add_copy_spec("/var/log/libvirt") + +- if os.path.exists(libvirt_keytab): ++ 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") +-- +1.8.3.1 + + +From b34ea0c6ea5449bbd2f4f9624e1644dc01b07e9d Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Mon, 26 Jan 2015 00:09:11 +0000 +Subject: [PATCH 17/38] [logs] fix do_regex_find_all() use for --sysroot + +The logs plugin searches syslog configuration files. When using +--sysroot the plugin needs to use join_sysroot() to open the +correct path. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/logs.py | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/sos/plugins/logs.py b/sos/plugins/logs.py +index 2f86acc..7957898 100644 +--- a/sos/plugins/logs.py ++++ b/sos/plugins/logs.py +@@ -38,12 +38,12 @@ class Logs(Plugin): + ]) + + if self.get_option('all_logs'): +- logs = self.do_regex_find_all("^\S+\s+(-?\/.*$)\s+", +- "/etc/syslog.conf") ++ 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"): + logs += self.do_regex_find_all("^\S+\s+(-?\/.*$)\s+", +- "/etc/rsyslog.conf") ++ rsyslog_conf) + for i in logs: + if i.startswith("-"): + i = i[1:] +@@ -74,7 +74,7 @@ class RedHatLogs(Logs, RedHatPlugin): + 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 five days worth of logs by default if the system is ++ # 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: +-- +1.8.3.1 + + +From 534eb7fe732ec366292ec582ec2891ef0648ffcb Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Mon, 26 Jan 2015 00:11:15 +0000 +Subject: [PATCH 18/38] [lvm2] don't chroot if tmp is not inside sysroot + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/lvm2.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sos/plugins/lvm2.py b/sos/plugins/lvm2.py +index dd10fa7..c626231 100644 +--- a/sos/plugins/lvm2.py ++++ b/sos/plugins/lvm2.py +@@ -37,7 +37,7 @@ class Lvm2(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin): + lvmdump_opts = "-a -m" + cmd = lvmdump_cmd % (lvmdump_opts, + self.get_cmd_output_path(name="lvmdump")) +- self.add_cmd_output(cmd) ++ self.add_cmd_output(cmd, chroot=self.tmp_in_sysroot()) + + def setup(self): + # use locking_type 0 (no locks) when running LVM2 commands, +-- +1.8.3.1 + + +From f4218ff5bab93908ca3d0804c9d837bdfa57f654 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Mon, 26 Jan 2015 00:37:32 +0000 +Subject: [PATCH 19/38] [docs] add --chroot to sosreport.1 + +Signed-off-by: Bryn M. Reeves +--- + man/en/sosreport.1 | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/man/en/sosreport.1 b/man/en/sosreport.1 +index b0a86f2..f36f845 100644 +--- a/man/en/sosreport.1 ++++ b/man/en/sosreport.1 +@@ -13,6 +13,7 @@ sosreport \- Collect and package diagnostic and support data + [--batch] [--build] [--debug]\fR + [--name name] [--case-id id] [--ticket-number nr] + [-s|--sysroot]\fR ++ [-c|--chroot {auto|always|never}\fR + [--tmp-dir directory]\fR + [-p|--profile profile-name]\fR + [--list-profiles]\fR +@@ -77,6 +78,13 @@ Specify alternate configuration file. + Specify an alternate root file system path. Useful for collecting + reports from containers and images. + .TP ++.B \-c, \--chroot {auto|always|never} ++Set the chroot mode. When \--sysroot is used commands default to ++executing with SYSROOT as the root directory (unless disabled by ++a specific plugin). This can be overriden by setting \--chroot to ++"always" (alwyas chroot) or "never" (always run in the host ++namespace). ++.TP + .B \--tmp-dir DIRECTORY + Specify alternate temporary directory to copy data as well as the + compressed report. +-- +1.8.3.1 + + +From fb1b4a8b6793611ed91f43f6d3553351c704f50f Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Mon, 26 Jan 2015 14:57:01 +0000 +Subject: [PATCH 20/38] [plugin] handle ELOOP in _copy_dir() + +A problem with systemd's management of the binfmt_misc automount +point in Atomic environments causes attempts to access this path to +fail with ELOOP: + + >>> import os + >>> os.listdir("/host/proc/sys/fs/binfmt_misc/") + Traceback (most recent call last): + File "", line 1, in + OSError: [Errno 2] No such file or directory: '/host/proc/sys/fs/binfmt_misc/' + +For reasons that are not yet clear this causes the entire sos +process to immediately terminate. + +For now avoid the problem by enclosing the problem os.listdir in +a try/except block that explicitly handles the one errno value +implicated here. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/__init__.py | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/sos/plugins/__init__.py b/sos/plugins/__init__.py +index fd1acb5..b206470 100644 +--- a/sos/plugins/__init__.py ++++ b/sos/plugins/__init__.py +@@ -27,6 +27,7 @@ import stat + from time import time + import logging + import fnmatch ++import errno + + # PYCOMPAT + import six +@@ -303,10 +304,17 @@ class Plugin(object): + 'pointsto': linkdest}) + + def _copy_dir(self, srcpath): +- 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) ++ 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(): +-- +1.8.3.1 + + +From 2c1af0457b668acb99129ed1f6dedcf7cdaa0eea Mon Sep 17 00:00:00 2001 +From: Neependra Khare +Date: Mon, 26 Jan 2015 15:04:07 +0000 +Subject: [PATCH 21/38] [kubernetes] new plugin + +Add a plugin for Kubernetes support. + +Signed-off-by: Neependra Khare +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/kubernetes.py | 46 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 46 insertions(+) + create mode 100644 sos/plugins/kubernetes.py + +diff --git a/sos/plugins/kubernetes.py b/sos/plugins/kubernetes.py +new file mode 100644 +index 0000000..af3f3a6 +--- /dev/null ++++ b/sos/plugins/kubernetes.py +@@ -0,0 +1,46 @@ ++# 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 ++ """ ++ ++ def setup(self): ++ self.add_copy_spec("/etc/kubernetes") ++ self.add_copy_spec("/etc/etcd") ++ 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 minions") ++ self.add_cmd_output("kubectl get -o json replicationController") ++ self.add_cmd_output("kubectl get -o json events") ++ self.add_cmd_output("journalctl -r -u kubelet") ++ ++ # etcd ++ self.add_cmd_output("curl http://127.0.0.1:4001/version") ++ self.add_cmd_output("curl http://127.0.0.1:4001/v2/members") ++ self.add_cmd_output("curl http://127.0.0.1:4001/v2/stats/leader") ++ self.add_cmd_output("curl http://127.0.0.1:4001/v2/stats/self") ++ self.add_cmd_output("curl http://127.0.0.1:4001/v2/stats/store") ++ ++ ++# vim: et ts=5 sw=4 +-- +1.8.3.1 + + +From 550dda69c6c5d527498ad928a29c466fad4e250e Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Mon, 26 Jan 2015 17:32:35 +0000 +Subject: [PATCH 22/38] [docs] fix documentation of --sysroot parameter + +Signed-off-by: Bryn M. Reeves +--- + man/en/sosreport.1 | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/man/en/sosreport.1 b/man/en/sosreport.1 +index f36f845..eac9047 100644 +--- a/man/en/sosreport.1 ++++ b/man/en/sosreport.1 +@@ -12,7 +12,7 @@ sosreport \- Collect and package diagnostic and support data + [--no-report] [--config-file conf]\fR + [--batch] [--build] [--debug]\fR + [--name name] [--case-id id] [--ticket-number nr] +- [-s|--sysroot]\fR ++ [-s|--sysroot SYSROOT]\fR + [-c|--chroot {auto|always|never}\fR + [--tmp-dir directory]\fR + [-p|--profile profile-name]\fR +-- +1.8.3.1 + + +From d7cf8535a3403fe6050e0905bef2b4429e595664 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Mon, 26 Jan 2015 15:32:03 -0500 +Subject: [PATCH 23/38] [utilities] add chroot support to shell_out() + +Signed-off-by: Bryn M. Reeves +--- + sos/utilities.py | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/sos/utilities.py b/sos/utilities.py +index a82ac7c..6475619 100644 +--- a/sos/utilities.py ++++ b/sos/utilities.py +@@ -186,11 +186,12 @@ def import_module(module_fqname, superclasses=None): + return modules + + +-def shell_out(cmd, timeout=30, runat=None): ++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, chdir=runat)['output'] ++ return sos_get_command_output(cmd, timeout=timeout, ++ chroot=chroot, chdir=runat)['output'] + + + class ImporterHelper(object): +-- +1.8.3.1 + + +From a1a1fd6cfcdb62d7af7744bb5710a2c7d5b4262a Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Mon, 26 Jan 2015 15:33:18 -0500 +Subject: [PATCH 24/38] [policies] make PackageManager and Policy sysroot-aware + +Add methods to Policy to get the host root file system path and +to test if sos is running in a container and allow Policy classes +to pass a chroot path into the PackageManager constructor in order +to obtain package data from the chroot. + +Signed-off-by: Bryn M. Reeves +--- + sos/policies/__init__.py | 22 ++++++++++++++++++++-- + 1 file changed, 20 insertions(+), 2 deletions(-) + +diff --git a/sos/policies/__init__.py b/sos/policies/__init__.py +index 4657614..cea4c09 100644 +--- a/sos/policies/__init__.py ++++ b/sos/policies/__init__.py +@@ -57,11 +57,14 @@ class PackageManager(object): + + query_command = None + timeout = 30 ++ chroot = None + +- def __init__(self, query_command=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): + """ +@@ -93,7 +96,11 @@ class PackageManager(object): + version': 'major.minor.version'}} + """ + if self.query_command: +- pkg_list = shell_out(self.query_command, self.timeout).splitlines() ++ 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 +@@ -145,6 +152,9 @@ No changes will be made to system configuration. + vendor_text = "" + PATH = "" + ++ _in_container = False ++ _host_sysroot = '/' ++ + def __init__(self): + """Subclasses that choose to override this initializer should call + super() to ensure that they get the required platform bits attached. +@@ -180,6 +190,14 @@ No changes will be made to system configuration. + """ + 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 +-- +1.8.3.1 + + +From 63805ed15d63ddfebb06cd03f96f310bbf60d3b2 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Mon, 26 Jan 2015 15:36:40 -0500 +Subject: [PATCH 25/38] [policies] add container support to Red Hat policy + +Check for the presence of container-specific environment variables +and set _host_sysroot if present: + + container_uuid=UUID + HOST=/path + +If both a container environment variable and HOST are present run +the PackageManager query command in a chroot. + +Signed-off-by: Bryn M. Reeves +--- + sos/policies/redhat.py | 23 +++++++++++++++++++++-- + 1 file changed, 21 insertions(+), 2 deletions(-) + +diff --git a/sos/policies/redhat.py b/sos/policies/redhat.py +index d2f8db0..f1db8ac 100644 +--- a/sos/policies/redhat.py ++++ b/sos/policies/redhat.py +@@ -38,13 +38,17 @@ class RedHatPolicy(LinuxPolicy): + vendor = "Red Hat" + vendor_url = "http://www.redhat.com/" + _tmp_dir = "/var/tmp" ++ _rpmq_cmd = 'rpm -qa --queryformat "%{NAME}|%{VERSION}\\n"' ++ _in_container = False ++ _host_sysroot = '/' + + def __init__(self): + super(RedHatPolicy, self).__init__() + self.report_name = "" + self.ticket_number = "" +- self.package_manager = PackageManager( +- 'rpm -qa --queryformat "%{NAME}|%{VERSION}\\n"') ++ # need to set _host_sysroot before PackageManager() ++ sysroot = self._container_init() ++ self.package_manager = PackageManager(self._rpmq_cmd, chroot=sysroot) + self.valid_subclasses = [RedHatPlugin] + + pkgs = self.package_manager.all_pkgs() +@@ -70,6 +74,17 @@ class RedHatPolicy(LinuxPolicy): + 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 if a host sysroot ++ has been passed in the environment. ++ """ ++ 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 != '/' ++ return self._host_sysroot if use_sysroot else None ++ + def runlevel_by_service(self, name): + from subprocess import Popen, PIPE + ret = [] +@@ -100,6 +115,10 @@ class RedHatPolicy(LinuxPolicy): + 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" +-- +1.8.3.1 + + +From f8a1746a871e560e548d21f1fc68067d452140a0 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Mon, 26 Jan 2015 15:39:16 -0500 +Subject: [PATCH 26/38] [sosreport] set SYSROOT by policy + +If --sysroot is not given on the command line and +Policy.in_container() is True set sysroot automatically if +Policy.get_host_sysroot() is not '/'. + +Signed-off-by: Bryn M. Reeves +--- + sos/sosreport.py | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/sos/sosreport.py b/sos/sosreport.py +index a0b89e7..835d828 100644 +--- a/sos/sosreport.py ++++ b/sos/sosreport.py +@@ -648,7 +648,7 @@ class SoSOptions(object): + help="Disable HTML/XML reporting", default=False) + parser.add_option("-s", "--sysroot", action="store", dest="sysroot", + help="system root directory path (default='/')", +- default="/") ++ default=None) + parser.add_option("-c", "--chroot", action="store", dest="chroot", + help="chroot executed commands to SYSROOT " + "[auto, always, never] (default=auto)", +@@ -705,11 +705,18 @@ class SoSReport(object): + self.tempfile_util = TempFileUtil(self.tmpdir) + self._set_directories() + ++ self._setup_logging() ++ ++ msg = "default" ++ host_sysroot = self.policy.host_sysroot() + # set alternate system root directory + if self.opts.sysroot: ++ msg = "cmdline" + self.sysroot = self.opts.sysroot +- +- self._setup_logging() ++ elif self.policy.in_container() and host_sysroot != os.sep: ++ msg = "policy" ++ self.sysroot = host_sysroot ++ self.soslog.debug("set sysroot to '%s' (%s)" % (self.sysroot, msg)) + + if self.opts.chroot not in chroot_modes: + self.soslog.error("invalid chroot mode: %s" % self.opts.chroot) +-- +1.8.3.1 + + +From fac57721ae10dafec909c4fac408f42ebe23d4ac Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Mon, 26 Jan 2015 16:14:01 -0500 +Subject: [PATCH 27/38] [firewalld] work around command hangs in container + environments + +Add a 10s timeout to firewalld-cmd execution to avoid long dbus +timeouts in docker containers. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/firewalld.py | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/sos/plugins/firewalld.py b/sos/plugins/firewalld.py +index 98d011b..8eeb2b6 100644 +--- a/sos/plugins/firewalld.py ++++ b/sos/plugins/firewalld.py +@@ -35,9 +35,11 @@ class FirewallD(Plugin, RedHatPlugin): + "/etc/sysconfig/firewalld" + ]) + ++ # use a 10s timeout to workaround dbus problems in ++ # docker containers. + self.add_cmd_output([ + "firewall-cmd --list-all-zones", + "firewall-cmd --permanent --list-all-zones" +- ]) ++ ], timeout=10) + + # vim: et ts=4 sw=4 +-- +1.8.3.1 + + +From 6a239ddeb5de9a04e7e7081ea6425d89dddda3f5 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Mon, 26 Jan 2015 17:13:24 -0500 +Subject: [PATCH 28/38] [policies] pass --sysroot down to policy classes + +Policies that don't auto-detect a container environment with a +host file system need to pass the value of --sysroot down to the +PackageManager class in order to obtain package details from the +chroot environment. + +Signed-off-by: Bryn M. Reeves +--- + sos/policies/__init__.py | 11 ++++++----- + sos/policies/debian.py | 4 ++-- + sos/policies/redhat.py | 18 +++++++++++------- + sos/policies/ubuntu.py | 4 ++-- + sos/sosreport.py | 2 +- + 5 files changed, 22 insertions(+), 17 deletions(-) + +diff --git a/sos/policies/__init__.py b/sos/policies/__init__.py +index cea4c09..a403bb9 100644 +--- a/sos/policies/__init__.py ++++ b/sos/policies/__init__.py +@@ -28,7 +28,7 @@ def import_policy(name): + return None + + +-def load(cache={}): ++def load(cache={}, sysroot=None): + if 'policy' in cache: + return cache.get('policy') + +@@ -37,7 +37,7 @@ def load(cache={}): + for module in helper.get_modules(): + for policy in import_policy(module): + if policy.check(): +- cache['policy'] = policy() ++ cache['policy'] = policy(sysroot=sysroot) + + if 'policy' not in cache: + cache['policy'] = GenericPolicy() +@@ -155,7 +155,7 @@ No changes will be made to system configuration. + _in_container = False + _host_sysroot = '/' + +- def __init__(self): ++ 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 +@@ -167,6 +167,7 @@ No changes will be made to system configuration. + 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 +@@ -372,8 +373,8 @@ class LinuxPolicy(Policy): + vendor = "None" + PATH = "/bin:/sbin:/usr/bin:/usr/sbin" + +- def __init__(self): +- super(LinuxPolicy, self).__init__() ++ def __init__(self, sysroot=None): ++ super(LinuxPolicy, self).__init__(sysroot=sysroot) + + def get_preferred_hash_algorithm(self): + checksum = "md5" +diff --git a/sos/policies/debian.py b/sos/policies/debian.py +index acb5b85..e56e546 100644 +--- a/sos/policies/debian.py ++++ b/sos/policies/debian.py +@@ -16,8 +16,8 @@ class DebianPolicy(LinuxPolicy): + PATH = "/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games" \ + + ":/usr/local/sbin:/usr/local/bin" + +- def __init__(self): +- super(DebianPolicy, self).__init__() ++ def __init__(self, sysroot=None): ++ super(DebianPolicy, self).__init__(sysroot=sysroot) + self.report_name = "" + self.ticket_number = "" + self.package_manager = PackageManager( +diff --git a/sos/policies/redhat.py b/sos/policies/redhat.py +index f1db8ac..f20359d 100644 +--- a/sos/policies/redhat.py ++++ b/sos/policies/redhat.py +@@ -42,12 +42,16 @@ class RedHatPolicy(LinuxPolicy): + _in_container = False + _host_sysroot = '/' + +- def __init__(self): +- super(RedHatPolicy, self).__init__() ++ def __init__(self, sysroot=None): ++ super(RedHatPolicy, self).__init__(sysroot=sysroot) + self.report_name = "" + self.ticket_number = "" + # need to set _host_sysroot before PackageManager() +- sysroot = self._container_init() ++ 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] + +@@ -145,8 +149,8 @@ No changes will be made to system configuration. + %(vendor_text)s + """) + +- def __init__(self): +- super(RHELPolicy, self).__init__() ++ def __init__(self, sysroot=None): ++ super(RHELPolicy, self).__init__(sysroot=sysroot) + + @classmethod + def check(self): +@@ -192,8 +196,8 @@ class FedoraPolicy(RedHatPolicy): + vendor = "the Fedora Project" + vendor_url = "https://fedoraproject.org/" + +- def __init__(self): +- super(FedoraPolicy, self).__init__() ++ def __init__(self, sysroot=None): ++ super(FedoraPolicy, self).__init__(sysroot=sysroot) + + @classmethod + def check(self): +diff --git a/sos/policies/ubuntu.py b/sos/policies/ubuntu.py +index 0dd2ea2..f236421 100644 +--- a/sos/policies/ubuntu.py ++++ b/sos/policies/ubuntu.py +@@ -9,8 +9,8 @@ class UbuntuPolicy(DebianPolicy): + vendor = "Ubuntu" + vendor_url = "http://www.ubuntu.com/" + +- def __init__(self): +- super(UbuntuPolicy, self).__init__() ++ def __init__(self, sysroot=None): ++ super(UbuntuPolicy, self).__init__(sysroot=sysroot) + self.valid_subclasses = [UbuntuPlugin, DebianPlugin] + + @classmethod +diff --git a/sos/sosreport.py b/sos/sosreport.py +index 835d828..ad13a2d 100644 +--- a/sos/sosreport.py ++++ b/sos/sosreport.py +@@ -687,7 +687,7 @@ class SoSReport(object): + self._read_config() + + try: +- self.policy = sos.policies.load() ++ self.policy = sos.policies.load(sysroot=self.opts.sysroot) + except KeyboardInterrupt: + self._exit(0) + +-- +1.8.3.1 + + +From d34bf4982f8a627901f6538be3b9e52cc30fe91b Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Tue, 27 Jan 2015 11:40:06 +0000 +Subject: [PATCH 29/38] [sosoptions] ensure '_sysroot' and '_chroot' are + initialised + +Make sure the sysroot and chroot members of the SoSOptions object +are initialised to prevent exceptions when these are not set on +the command line: + + sosreport + Traceback (most recent call last): + File "/usr/sbin/sosreport", line 25, in + main(sys.argv[1:]) + File "/usr/lib/python2.7/site-packages/sos/sosreport.py", line 1490, in main + sos = SoSReport(args) + File "/usr/lib/python2.7/site-packages/sos/sosreport.py", line 673, in __init__ + self.policy = sos.policies.load(sysroot=self.opts.sysroot) + File "/usr/lib/python2.7/site-packages/sos/policies/__init__.py", line 40, in load + cache['policy'] = policy(sysroot=sysroot) + File "/usr/lib/python2.7/site-packages/sos/policies/redhat.py", line 192, in __init__ + super(FedoraPolicy, self).__init__(sysroot=sysroot) + File "/usr/lib/python2.7/site-packages/sos/policies/redhat.py", line 58, in __init__ + if self.package_manager.all_pkgs()['filesystem']['version'][0] == '3': + File "/usr/lib/python2.7/site-packages/sos/policies/__init__.py", line 116, in all_pkgs + self.packages = self.get_pkg_list() + File "/usr/lib/python2.7/site-packages/sos/policies/__init__.py", line 99, in get_pkg_list + pkg_list = shell_out(cmd, chroot=self.chroot).splitlines() + File "/usr/lib/python2.7/site-packages/sos/utilities.py", line 191, in shell_out + return sos_get_command_output(cmd, chroot=chroot, chdir=runat)['output'] + File "/usr/lib/python2.7/site-packages/sos/utilities.py", line 156, in sos_get_command_output + raise e + OSError: [Errno 1] Operation not permitted: '/' + +Signed-off-by: Bryn M. Reeves +--- + sos/sosreport.py | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sos/sosreport.py b/sos/sosreport.py +index ad13a2d..27c756f 100644 +--- a/sos/sosreport.py ++++ b/sos/sosreport.py +@@ -251,6 +251,8 @@ class SoSOptions(object): + _config_file = "" + _tmp_dir = "" + _report = True ++ _sysroot = None ++ _chroot = 'auto' + _compression_type = 'auto' + + _options = None +-- +1.8.3.1 + + +From c0858c2c87f246283f6c59b7bf7f64f7dea73a82 Mon Sep 17 00:00:00 2001 +From: Neependra Khare +Date: Tue, 27 Jan 2015 15:54:23 +0000 +Subject: [PATCH 30/38] [etcd] split etcd functionality from kubernetes into + new plugin + +Signed-off-by: Neependra Khare +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/etcd.py | 36 ++++++++++++++++++++++++++++++++++++ + sos/plugins/kubernetes.py | 8 -------- + 2 files changed, 36 insertions(+), 8 deletions(-) + create mode 100644 sos/plugins/etcd.py + +diff --git a/sos/plugins/etcd.py b/sos/plugins/etcd.py +new file mode 100644 +index 0000000..69edca0 +--- /dev/null ++++ b/sos/plugins/etcd.py +@@ -0,0 +1,36 @@ ++# 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 +diff --git a/sos/plugins/kubernetes.py b/sos/plugins/kubernetes.py +index af3f3a6..289d784 100644 +--- a/sos/plugins/kubernetes.py ++++ b/sos/plugins/kubernetes.py +@@ -24,7 +24,6 @@ class kubernetes(Plugin, RedHatPlugin): + + def setup(self): + self.add_copy_spec("/etc/kubernetes") +- self.add_copy_spec("/etc/etcd") + self.add_copy_spec("/var/run/flannel") + + # Kubernetes master info +@@ -35,12 +34,5 @@ class kubernetes(Plugin, RedHatPlugin): + self.add_cmd_output("kubectl get -o json events") + self.add_cmd_output("journalctl -r -u kubelet") + +- # etcd +- self.add_cmd_output("curl http://127.0.0.1:4001/version") +- self.add_cmd_output("curl http://127.0.0.1:4001/v2/members") +- self.add_cmd_output("curl http://127.0.0.1:4001/v2/stats/leader") +- self.add_cmd_output("curl http://127.0.0.1:4001/v2/stats/self") +- self.add_cmd_output("curl http://127.0.0.1:4001/v2/stats/store") +- + + # vim: et ts=5 sw=4 +-- +1.8.3.1 + + +From 2ddc706c7219d0b891304fcb066dea865f8516b5 Mon Sep 17 00:00:00 2001 +From: Neependra Khare +Date: Tue, 27 Jan 2015 15:58:32 +0000 +Subject: [PATCH 31/38] [kubernetes] add services and pod logs collection + +Signed-off-by: Neependra Khare +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/kubernetes.py | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/sos/plugins/kubernetes.py b/sos/plugins/kubernetes.py +index 289d784..9c2df5e 100644 +--- a/sos/plugins/kubernetes.py ++++ b/sos/plugins/kubernetes.py +@@ -22,6 +22,8 @@ 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") +@@ -30,9 +32,19 @@ class kubernetes(Plugin, RedHatPlugin): + self.add_cmd_output("kubectl version") + self.add_cmd_output("kubectl get -o json pods") + self.add_cmd_output("kubectl get -o json minions") ++ 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 -r -u kubelet") + ++ 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 +-- +1.8.3.1 + + +From 259897b60b0e4ee00585a8d73521fa4e291eb8da Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Tue, 27 Jan 2015 12:54:31 -0500 +Subject: [PATCH 32/38] [policies/redhat] automatically set tmp_dir in + containers + +Now that policies have the infrastructure to detect that they +are running in a container and to use the HOST environment +variable if present enable automatic setting of self._tmp_dir in +appriate container environments. + +This causes reports to be automatically written to $HOST/var/tmp +when $HOST is set while still allowing users to override the tmp +path manually by specificying --tmp-dir=PATH. + +Signed-off-by: Bryn M. Reeves +--- + sos/policies/redhat.py | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/sos/policies/redhat.py b/sos/policies/redhat.py +index f20359d..3cf40b3 100644 +--- a/sos/policies/redhat.py ++++ b/sos/policies/redhat.py +@@ -79,14 +79,17 @@ class RedHatPolicy(LinuxPolicy): + return False + + def _container_init(self): +- """Check if sos is running in a container and if a host sysroot +- has been passed in the environment. ++ """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): +-- +1.8.3.1 + + +From b880c6cb4668815b97841e6532450144a5f825f1 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Tue, 27 Jan 2015 13:53:34 -0500 +Subject: [PATCH 33/38] [policies/redhat] add Red Hat Atomic Host policy + +Add a new policy for the Red Hat Atomic Host. + +Signed-off-by: Bryn M. Reeves +--- + sos/policies/redhat.py | 39 ++++++++++++++++++++++++++++++++++++++- + 1 file changed, 38 insertions(+), 1 deletion(-) + +diff --git a/sos/policies/redhat.py b/sos/policies/redhat.py +index 3cf40b3..9decd0a 100644 +--- a/sos/policies/redhat.py ++++ b/sos/policies/redhat.py +@@ -37,6 +37,7 @@ 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 +@@ -159,7 +160,7 @@ No changes will be made to system configuration. + def check(self): + """This method checks to see if we are running on RHEL. It returns True + or False.""" +- return (os.path.isfile('/etc/redhat-release') ++ return (os.path.isfile(self._redhat_release) + and not os.path.isfile('/etc/fedora-release')) + + def dist_version(self): +@@ -193,6 +194,42 @@ No changes will be made to system configuration. + 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" +-- +1.8.3.1 + + +From cd0d5c1f06a69c115e674f87254cc7e056c9891a Mon Sep 17 00:00:00 2001 +From: Jeremy Eder +Date: Wed, 28 Jan 2015 12:54:14 +0000 +Subject: [PATCH 34/38] [docker] add 'docker' to the package list for Red Hat + distros + +The docker package is named 'docker-io' in Fedora and 'docker' +in RHEL and other downstream products. Add the 'docker' name to +the package list in RedHatDocker to ensure the plugin runs. + +Signed-off-by: Jeremy Eder +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/docker.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sos/plugins/docker.py b/sos/plugins/docker.py +index 3e5bd4a..c5ea8a0 100644 +--- a/sos/plugins/docker.py ++++ b/sos/plugins/docker.py +@@ -54,7 +54,7 @@ class Docker(Plugin): + + class RedHatDocker(Docker, RedHatPlugin): + +- packages = ('docker-io',) ++ packages = ('docker', 'docker-io') + + def setup(self): + super(RedHatDocker, self).setup() +-- +1.8.3.1 + + +From d4ae63afbf211a7234b7605bef037d827263bf70 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Wed, 28 Jan 2015 22:54:48 +0000 +Subject: [PATCH 35/38] [plugins] automatically re-try chroot'ed commands in + the host + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/__init__.py | 12 +++++++++++- + sos/utilities.py | 5 +---- + 2 files changed, 12 insertions(+), 5 deletions(-) + +diff --git a/sos/plugins/__init__.py b/sos/plugins/__init__.py +index b206470..7fa7ac6 100644 +--- a/sos/plugins/__init__.py ++++ b/sos/plugins/__init__.py +@@ -520,13 +520,23 @@ class Plugin(object): + 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)) +- # 126 means 'found but not executable' ++ ++ # 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 + +diff --git a/sos/utilities.py b/sos/utilities.py +index 6475619..d3a1048 100644 +--- a/sos/utilities.py ++++ b/sos/utilities.py +@@ -151,16 +151,13 @@ def sos_get_command_output(command, timeout=300, stderr=False, + 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 + +- stdout, stderr = p.communicate() +- +- # Required hack while we still pass shell=True to Popen; a Popen +- # call with shell=False for a non-existant binary will raise OSError. + if p.returncode == 126 or p.returncode == 127: + stdout = six.binary_type(b"") + +-- +1.8.3.1 + + +From 6fe240a31c01d63957ce548f4415ca55859dc071 Mon Sep 17 00:00:00 2001 +From: Neependra Khare +Date: Thu, 29 Jan 2015 18:23:53 +0000 +Subject: [PATCH 36/38] [kubernetes] add journal output for kube services + +Add journalctl output for the following kubernetes units: + + kube-apiserver + kube-controller-manager + kube-scheduler + kube-proxy + +Signed-off-by: Neependra Khare +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/kubernetes.py | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/sos/plugins/kubernetes.py b/sos/plugins/kubernetes.py +index 9c2df5e..38faeb2 100644 +--- a/sos/plugins/kubernetes.py ++++ b/sos/plugins/kubernetes.py +@@ -36,6 +36,10 @@ class kubernetes(Plugin, RedHatPlugin): + self.add_cmd_output("kubectl get -o json replicationController") + self.add_cmd_output("kubectl get -o json events") + self.add_cmd_output("journalctl -r -u kubelet") ++ self.add_cmd_output("journalctl -r -u kube-apiserver") ++ self.add_cmd_output("journalctl -r -u kube-controller-manager") ++ self.add_cmd_output("journalctl -r -u kube-scheduler") ++ self.add_cmd_output("journalctl -r -u kube-proxy") + + if self.get_option('podslog'): + result = self.get_command_output("kubectl get pods") +-- +1.8.3.1 + + +From 8d69d74a5be6dac29fad2ab5d7206a0485969924 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Thu, 29 Jan 2015 20:30:31 +0000 +Subject: [PATCH 37/38] [plugins] do not strip SYSROOT when copying link + targets + +The abspath() call in _copy_symlink returns a host-relative path +(when SYSROOT is not '/'). Pass this directly to _do_copy_path() +without stripping the SYSROOT path component. + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/__init__.py | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/sos/plugins/__init__.py b/sos/plugins/__init__.py +index 7fa7ac6..a7c0146 100644 +--- a/sos/plugins/__init__.py ++++ b/sos/plugins/__init__.py +@@ -265,7 +265,8 @@ class Plugin(object): + # 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 ++ # 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): +-- +1.8.3.1 + + +From 76c04a773f1927359d264f59e4fbcc9363424882 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Thu, 29 Jan 2015 22:00:10 +0000 +Subject: [PATCH 38/38] [plugins] trim leading '../' from links when sysroot is + set + +When SYSROOT is not '/' relative symlinks need to be trimmed to +remove the extra leading '../' returned by +abspath('/sysroot/...'). + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/__init__.py | 3 +++ + sos/sosreport.py | 1 + + 2 files changed, 4 insertions(+) + +diff --git a/sos/plugins/__init__.py b/sos/plugins/__init__.py +index a7c0146..a06c0b1 100644 +--- a/sos/plugins/__init__.py ++++ b/sos/plugins/__init__.py +@@ -271,6 +271,9 @@ class Plugin(object): + # 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: +diff --git a/sos/sosreport.py b/sos/sosreport.py +index 27c756f..567e3df 100644 +--- a/sos/sosreport.py ++++ b/sos/sosreport.py +@@ -1226,6 +1226,7 @@ class SoSReport(object): + self.ui_log.error(" %s while setting up plugins" + % e.strerror) + self.ui_log.error("") ++ self._exit(1) + if self.raise_plugins: + raise + self._log_plugin_exception(plugname, "setup") +-- +1.8.3.1 + +From bb6f546603d8e3199bda0bfe0f9b23f1da1cb8c9 Mon Sep 17 00:00:00 2001 +From: Pavel Moravec +Date: Mon, 13 Jul 2015 15:03:37 +0200 +Subject: [PATCH] [plugin] pass stderr through _collect_cmd_output + +Commit f06efd6 removed passing stderr in _collect_cmd_output to +get_cmd_output_now. That prevents passing stderr=False in several +scenarios. + +This fix adds the argument to be passed back. + +Resolves: #600 + +Signed-off-by: Pavel Moravec +--- + sos/plugins/__init__.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sos/plugins/__init__.py b/sos/plugins/__init__.py +index a06c0b1..aed7496 100644 +--- a/sos/plugins/__init__.py ++++ b/sos/plugins/__init__.py +@@ -696,7 +696,7 @@ class Plugin(object): + self._log_info("collecting output of '%s'" % prog) + self.get_cmd_output_now(prog, suggest_filename=suggest_filename, + root_symlink=root_symlink, timeout=timeout, +- chroot=chroot, runat=runat) ++ stderr=stderr, chroot=chroot, runat=runat) + + def _collect_strings(self): + for string, file_name in self.copy_strings: +-- +1.8.3.1 + diff --git a/sos-sos-ticket-number-name-params.patch b/sos-sos-ticket-number-name-params.patch new file mode 100644 index 0000000..ed6c475 --- /dev/null +++ b/sos-sos-ticket-number-name-params.patch @@ -0,0 +1,62 @@ +From 75901ef7906690aadaabc8925ac9a2e8523ed1a3 Mon Sep 17 00:00:00 2001 +From: Pavel Moravec +Date: Sun, 1 Feb 2015 13:40:18 +0100 +Subject: [PATCH] [general] Better handling --name and --ticket-number in + interactive mode + +Carry forward values from the CLI options into the interactive mode, +resolves #485 + +Signed-off-by: Pavel Moravec +--- + sos/policies/__init__.py | 19 +++++++++++-------- + 1 file changed, 11 insertions(+), 8 deletions(-) + +diff --git a/sos/policies/__init__.py b/sos/policies/__init__.py +index 34a2f6a..4c42d02 100644 +--- a/sos/policies/__init__.py ++++ b/sos/policies/__init__.py +@@ -402,17 +402,20 @@ class LinuxPolicy(Policy): + def pre_work(self): + # this method will be called before the gathering begins + +- localname = self.get_local_name() ++ 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 self.commons['cmdlineopts'].batch and not \ +- self.commons['cmdlineopts'].quiet: ++ 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: ")) ++ "report for [%s]: ") % caseid) + self._print() + except: + self._print() +@@ -421,11 +424,11 @@ class LinuxPolicy(Policy): + if len(self.report_name) == 0: + self.report_name = localname + +- if self.commons['cmdlineopts'].customer_name: +- self.report_name = self.commons['cmdlineopts'].customer_name ++ if customer_name: ++ self.report_name = customer_name + +- if self.commons['cmdlineopts'].case_id: +- self.case_id = self.commons['cmdlineopts'].case_id ++ 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: +-- +1.8.3.1 + diff --git a/sos-sos-unicode-use-errors-ignore.patch b/sos-sos-unicode-use-errors-ignore.patch new file mode 100644 index 0000000..1e9f66b --- /dev/null +++ b/sos-sos-unicode-use-errors-ignore.patch @@ -0,0 +1,61 @@ +diff -up sos-3.2/sos/archive.py.orig sos-3.2/sos/archive.py +--- sos-3.2/sos/archive.py.orig 2014-12-17 13:08:57.492362543 +0000 ++++ sos-3.2/sos/archive.py 2014-12-17 13:09:22.256522491 +0000 +@@ -388,9 +388,9 @@ class TarFileArchive(FileCacheArchive): + close_fds=True) + stdout, stderr = p.communicate() + if stdout: +- self.log_info(stdout.decode('utf-8')) ++ self.log_info(stdout.decode('utf-8', 'ignore')) + if stderr: +- self.log_error(stderr.decode('utf-8')) ++ self.log_error(stderr.decode('utf-8', 'ignore')) + self._suffix += suffix + return self.name() + except Exception as e: +diff -up sos-3.2/sos/plugins/__init__.py.orig sos-3.2/sos/plugins/__init__.py +--- sos-3.2/sos/plugins/__init__.py.orig 2014-12-17 13:08:57.493362550 +0000 ++++ sos-3.2/sos/plugins/__init__.py 2014-12-17 13:09:22.257522498 +0000 +@@ -541,7 +541,7 @@ class Plugin(object): + 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') ++ 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, +@@ -610,7 +610,8 @@ class Plugin(object): + + def _collect_strings(self): + for string, file_name in self.copy_strings: +- content = "..." + (string.splitlines()[0]).decode('utf8') ++ content = "..." ++ content += (string.splitlines()[0]).decode('utf8', 'ignore') + self._log_info("collecting string '%s' as '%s'" + % (content, file_name)) + try: +diff -up sos-3.2/sos/utilities.py.orig sos-3.2/sos/utilities.py +--- sos-3.2/sos/utilities.py.orig 2014-12-17 13:09:16.709486664 +0000 ++++ sos-3.2/sos/utilities.py 2014-12-17 13:09:22.257522498 +0000 +@@ -140,7 +140,7 @@ def sos_get_command_output(command, time + + # shlex.split() reacts badly to unicode on older python runtimes. + if not six.PY3: +- command = command.encode('utf-8') ++ command = command.encode('utf-8', 'ignore') + args = shlex.split(command) + try: + p = Popen(args, shell=False, stdout=PIPE, stderr=STDOUT, +@@ -159,7 +159,10 @@ def sos_get_command_output(command, time + if p.returncode == 126 or p.returncode == 127: + stdout = six.binary_type(b"") + +- return {'status': p.returncode, 'output': stdout.decode('utf-8')} ++ return { ++ 'status': p.returncode, ++ 'output': stdout.decode('utf-8', 'ignore') ++ } + + + def import_module(module_fqname, superclasses=None): diff --git a/sos-sos-verify-profile-for-valid-plugins-only.patch b/sos-sos-verify-profile-for-valid-plugins-only.patch new file mode 100644 index 0000000..fbd5109 --- /dev/null +++ b/sos-sos-verify-profile-for-valid-plugins-only.patch @@ -0,0 +1,63 @@ +From df219b43b5edab9868cb7d7511f7da1c1f5e225a Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Wed, 1 Jul 2015 14:18:50 +0100 +Subject: [PATCH] [general] verify --profile contains valid plugins only + +If --profile contains an invalid profile name, stop, and +print the list of available profiles as well as the offending +profile name (helpful when multiple profiles have been specified). + +E.g.: + +sosreport (version 3.2) + +Unknown or inactive profile(s) provided: virtuous +The following profiles are available: + + boot boot, startup, systemd, udev + cluster +[...] + +Based on a patch from Pavel Moravec. + +Fixes #505. + +Signed-off-by: Bryn M. Reeves +--- + sos/sosreport.py | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/sos/sosreport.py.orig b/sos/sosreport.py +index 7ea7b33..2af9de5 100644 +--- a/sos/sosreport.py.orig ++++ b/sos/sosreport.py +@@ -844,6 +844,7 @@ class SoSReport(object): + self.plugin_names = deque() + self.profiles = set() + using_profiles = len(self.opts.profiles) ++ remaining_profiles = list(self.opts.profiles) + # validate and load plugins + for plug in plugins: + plugbase, ext = os.path.splitext(plug) +@@ -896,12 +897,21 @@ class SoSReport(object): + self._skip(plugin_class, _("not specified")) + continue + ++ for i in plugin_class.profiles: ++ if i in remaining_profiles: ++ remaining_profiles.remove(i) ++ + self._load(plugin_class) + except Exception as e: + self.soslog.warning(_("plugin %s does not install, " + "skipping: %s") % (plug, e)) + if self.raise_plugins: + raise ++ if len(remaining_profiles) > 0: ++ self.soslog.error(_("Unknown or inactive profile(s) provided:" ++ " %s") % ", ".join(remaining_profiles)) ++ self.list_profiles() ++ self._exit(1) + + def _set_all_options(self): + if self.opts.usealloptions: diff --git a/sos-sosreport-catch-oserror-in-execute.patch b/sos-sosreport-catch-oserror-in-execute.patch new file mode 100644 index 0000000..a516793 --- /dev/null +++ b/sos-sosreport-catch-oserror-in-execute.patch @@ -0,0 +1,71 @@ +From 95bb5df9eda253afed15fa81340d31e03c40fe94 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Tue, 13 Jan 2015 17:10:06 +0000 +Subject: [PATCH] [sosreport] catch OSError exceptions in SoSReport.execute() + +OSError exceptions during logging setup and tear down are not +currently handled: + + Traceback (most recent call last): + File "/usr/sbin/sosreport", line 25, in + main(sys.argv[1:]) + File "/usr/lib/python2.7/site-packages/sos/sosreport.py", line 1409, in main + sos.execute() + File "/usr/lib/python2.7/site-packages/sos/sosreport.py", line 1366, in execute + self._setup_logging() + File "/usr/lib/python2.7/site-packages/sos/sosreport.py", line 739, in _setup_logging + self.sos_log_file = self.get_temp_file() + File "/usr/lib/python2.7/site-packages/sos/sosreport.py", line 670, in get_temp_file + return self.tempfile_util.new() + File "/usr/lib/python2.7/site-packages/sos/sosreport.py", line 82, in new + fd, fname = tempfile.mkstemp(dir=self.tmp_dir) + File "/usr/lib64/python2.7/tempfile.py", line 304, in mkstemp + return _mkstemp_inner(dir, prefix, suffix, flags) + File "/usr/lib64/python2.7/tempfile.py", line 239, in _mkstemp_inner + fd = _os.open(file, flags, 0600) + OSError: [Errno 28] No space left on device: '/tmp/tmp.4ejNitjwcr/nospace_tmp/tmpBjPTOm' + +Address this by adding OSError to the list of caught exceptions +in the main SoSReport.execute() method. Wrap the exception branch +clean up in a try/except block to catch additional exceptions +while attempting to clean up (e.g. unlink failures following an +EROFS on the temporary archive path). + +Signed-off-by: Bryn M. Reeves +--- + sos/sosreport.py | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +diff --git a/sos/sosreport.py b/sos/sosreport.py +index 0dd26ad..2a16555 100644 +--- a/sos/sosreport.py ++++ b/sos/sosreport.py +@@ -1395,12 +1395,19 @@ class SoSReport(object): + self.version() + + return self.final_work() +- except (SystemExit, KeyboardInterrupt): +- if self.archive: +- self.archive.cleanup() +- if self.tempfile_util: +- self.tempfile_util.clean() +- return False ++ ++ except (OSError, SystemExit, KeyboardInterrupt): ++ try: ++ # archive and tempfile cleanup may fail due to a fatal ++ # OSError exception (ENOSPC, EROFS etc.). ++ if self.archive: ++ self.archive.cleanup() ++ if self.tempfile_util: ++ self.tempfile_util.clean() ++ except: ++ pass ++ ++ return False + + + def main(args): +-- +1.9.3 + diff --git a/sos-sosreport-do-not-make-logging-calls-after-oserror.patch b/sos-sosreport-do-not-make-logging-calls-after-oserror.patch new file mode 100644 index 0000000..6a3b057 --- /dev/null +++ b/sos-sosreport-do-not-make-logging-calls-after-oserror.patch @@ -0,0 +1,41 @@ +From ed44939d5988098feb3f3ddededd68a0a4b9a9df Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Tue, 13 Jan 2015 17:26:33 +0000 +Subject: [PATCH] [sosreport] do not make logging calls after OSError + +Following an OSError during archive setup the logging subsystem +is potentially in an inconsistent or unusable state (e.g. due to +a readonly file system error). + +Use the print function directly since we just need to report the +error and exit. + +Signed-off-by: Bryn M. Reeves +--- + sos/sosreport.py | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/sos/sosreport.py b/sos/sosreport.py +index 2a16555..3c0397c 100644 +--- a/sos/sosreport.py ++++ b/sos/sosreport.py +@@ -1091,10 +1091,13 @@ class SoSReport(object): + self._make_archive_paths() + return + except (OSError, IOError) as e: ++ # we must not use the logging subsystem here as it is potentially ++ # in an inconsistent or unreliable state (e.g. an EROFS for the ++ # file system containing our temporary log files). + if e.errno in fatal_fs_errors: +- self.ui_log.error("") +- self.ui_log.error(" %s while setting up archive" % e.strerror) +- self.ui_log.error("") ++ print("") ++ print(" %s while setting up archive" % e.strerror) ++ print("") + else: + raise e + except Exception as e: +-- +1.9.3 + diff --git a/sos-sosreport-fix-archive-permissions-regression.patch b/sos-sosreport-fix-archive-permissions-regression.patch new file mode 100644 index 0000000..7540058 --- /dev/null +++ b/sos-sosreport-fix-archive-permissions-regression.patch @@ -0,0 +1,39 @@ +From d7759d3ddae5fe99a340c88a1d370d65cfa73fd6 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Thu, 30 Oct 2014 16:46:01 +0000 +Subject: [PATCH] [sosreport] fix archive permissions regression + +Restore the umask save/restore around archive creation and ensure +the effective umask is 077 at the time of archive creation. + +Fixes #425. + +Signed-off-by: Bryn M. Reeves +--- + sos/sosreport.py | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/sos/sosreport.py b/sos/sosreport.py +index 664414f..99b5f47 100644 +--- a/sos/sosreport.py ++++ b/sos/sosreport.py +@@ -1327,6 +1327,7 @@ class SoSReport(object): + self._finish_logging() + # package up the results for the support organization + if not self.opts.build: ++ old_umask = os.umask(0o077) + if not self.opts.quiet: + print(_("Creating compressed archive...")) + # compression could fail for a number of reasons +@@ -1345,6 +1346,8 @@ class SoSReport(object): + raise + else: + return False ++ finally: ++ os.umask(old_umask) + else: + final_filename = self.archive.get_archive_path() + self.policy.display_results(final_filename, build=self.opts.build) +-- +1.9.3 + diff --git a/sos-sosreport-fix-silent-exception-handling.patch b/sos-sosreport-fix-silent-exception-handling.patch new file mode 100644 index 0000000..b3daec4 --- /dev/null +++ b/sos-sosreport-fix-silent-exception-handling.patch @@ -0,0 +1,52 @@ +diff -up sos-3.2/sos/sosreport.py.orig sos-3.2/sos/sosreport.py +--- sos-3.2/sos/sosreport.py.orig 2015-01-20 14:39:34.149596845 +0000 ++++ sos-3.2/sos/sosreport.py 2015-01-20 14:39:56.132654519 +0000 +@@ -1131,11 +1131,13 @@ class SoSReport(object): + % e.strerror) + self.ui_log.error("") + self._exit(1) ++ if self.raise_plugins: ++ raise ++ self._log_plugin_exception(plugname, "setup") + except: + if self.raise_plugins: + raise +- else: +- self._log_plugin_exception(plugname, "setup") ++ self._log_plugin_exception(plugname, "setup") + + def version(self): + """Fetch version information from all plugins and store in the report +@@ -1177,11 +1179,13 @@ class SoSReport(object): + % e.strerror) + self.ui_log.error("") + self._exit(1) ++ if self.raise_plugins: ++ raise ++ self._log_plugin_exception(plugname, "collect") + except: + if self.raise_plugins: + raise +- else: +- self._log_plugin_exception(plugname, "collect") ++ self._log_plugin_exception(plugname, "collect") + self.ui_log.info("") + + def report(self): +@@ -1324,12 +1328,13 @@ class SoSReport(object): + % e.strerror) + self.ui_log.error("") + self._exit(1) ++ if self.raise_plugins: ++ raise ++ self._log_plugin_exception(plugname, "postproc") + except: + if self.raise_plugins: + raise +- else: +- self._log_plugin_exception(plugname, "postproc") +- ++ self._log_plugin_exception(plugname, "postproc") + + def final_work(self): + # this must come before archive creation to ensure that log diff --git a/sos-sosreport-log-plugin-exceptions-to-file.patch b/sos-sosreport-log-plugin-exceptions-to-file.patch new file mode 100644 index 0000000..069f186 --- /dev/null +++ b/sos-sosreport-log-plugin-exceptions-to-file.patch @@ -0,0 +1,67 @@ +From 8b49485153cc7dc03cd974dbc3a100c81ef04720 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Mon, 19 Jan 2015 19:40:06 +0000 +Subject: [PATCH] [sosreport] log plugin exceptions to a file + +Add exception logging for the Plugin.postproc() method and move +plugin exceptions into a separate per-plugin log file. This is +less cluttered than pushing a multi-line traceback through the +soslog.error logger and matches the behaviour of older releases. + +Signed-off-by: Bryn M. Reeves +--- + sos/sosreport.py | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +diff --git a/sos/sosreport.py b/sos/sosreport.py +index 3c0397c..f17194a 100644 +--- a/sos/sosreport.py ++++ b/sos/sosreport.py +@@ -1071,8 +1071,14 @@ class SoSReport(object): + self.ui_log.info("") + self._exit() + +- def _log_plugin_exception(self, plugin_name): +- self.soslog.error("%s\n%s" % (plugin_name, traceback.format_exc())) ++ def _log_plugin_exception(self, plugin, method): ++ trace = traceback.format_exc() ++ msg = "caught exception in plugin method" ++ plugin_err_log = "%s-plugin-errors.txt" % plugin ++ logpath = os.path.join(self.logdir, plugin_err_log) ++ self.soslog.error('%s "%s.%s()"' % (msg, plugin, method)) ++ self.soslog.error('writing traceback to %s' % logpath) ++ self.archive.add_string("%s\n" % trace, logpath) + + def prework(self): + self.policy.pre_work() +@@ -1129,7 +1135,7 @@ class SoSReport(object): + if self.raise_plugins: + raise + else: +- self._log_plugin_exception(plugname) ++ self._log_plugin_exception(plugname, "setup") + + def version(self): + """Fetch version information from all plugins and store in the report +@@ -1175,7 +1181,7 @@ class SoSReport(object): + if self.raise_plugins: + raise + else: +- self._log_plugin_exception(plugname) ++ self._log_plugin_exception(plugname, "collect") + self.ui_log.info("") + + def report(self): +@@ -1321,6 +1327,9 @@ class SoSReport(object): + except: + if self.raise_plugins: + raise ++ else: ++ self._log_plugin_exception(plugname, "postproc") ++ + + def final_work(self): + # this must come before archive creation to ensure that log +-- +1.9.3 + diff --git a/sos-sosreport-prepare-report-in-a-private-subdirectory.patch b/sos-sosreport-prepare-report-in-a-private-subdirectory.patch new file mode 100644 index 0000000..4ac7b38 --- /dev/null +++ b/sos-sosreport-prepare-report-in-a-private-subdirectory.patch @@ -0,0 +1,310 @@ +diff -up sos-3.2/sos/policies/__init__.py.orig sos-3.2/sos/policies/__init__.py +--- sos-3.2/sos/policies/__init__.py.orig 2015-12-16 13:06:08.730706383 +0000 ++++ sos-3.2/sos/policies/__init__.py 2015-12-16 13:07:09.456189257 +0000 +@@ -10,11 +10,9 @@ from os import environ + + from sos.utilities import (ImporterHelper, + import_module, +- get_hash_name, + shell_out) + from sos.plugins import IndependentPlugin + from sos import _sos as _ +-import hashlib + from textwrap import fill + from six import print_ + from six.moves import input +@@ -284,43 +282,29 @@ No changes will be made to system config + 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): ++ def get_preferred_hash_name(self): + """Returns the string name of the hashlib-supported checksum algorithm + to use""" + return "md5" + +- def display_results(self, final_filename=None, build=False): ++ def display_results(self, archive, directory, checksum): ++ # Display results is called from the tail of SoSReport.final_work() ++ # ++ # Logging is already shutdown and all terminal output must use the ++ # print() call. + + # make sure a report exists +- if not final_filename: ++ if not archive and not directory: + 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() +- ++ if archive: + self._print(_("Your sosreport has been generated and saved " +- "in:\n %s") % final_filename) ++ "in:\n %s") % archive) + else: +- checksum = None + self._print(_("sosreport build tree is located at : %s" % +- final_filename)) ++ directory)) + + self._print() + if checksum: +@@ -371,20 +355,28 @@ class LinuxPolicy(Policy): + vendor = "None" + PATH = "/bin:/sbin:/usr/bin:/usr/sbin" + ++ _preferred_hash_name = None ++ + def __init__(self, sysroot=None): + super(LinuxPolicy, self).__init__(sysroot=sysroot) + +- def get_preferred_hash_algorithm(self): ++ def get_preferred_hash_name(self): ++ ++ if self._preferred_hash_name: ++ return self._preferred_hash_name ++ + checksum = "md5" + try: + fp = open("/proc/sys/crypto/fips_enabled", "r") + except: ++ self._preferred_hash_name = checksum + return checksum + + fips_enabled = fp.read() + if fips_enabled.find("1") >= 0: + checksum = "sha256" + fp.close() ++ self._preferred_hash_name = checksum + return checksum + + def default_runlevel(self): +diff -up sos-3.2/sos/sosreport.py.orig sos-3.2/sos/sosreport.py +--- sos-3.2/sos/sosreport.py.orig 2015-12-16 13:06:08.748706527 +0000 ++++ sos-3.2/sos/sosreport.py 2015-12-16 13:07:09.458189272 +0000 +@@ -32,7 +32,9 @@ from sos.utilities import ImporterHelper + from stat import ST_UID, ST_GID, ST_MODE, ST_CTIME, ST_ATIME, ST_MTIME, S_IMODE + from time import strftime, localtime + from collections import deque ++from shutil import rmtree + import tempfile ++import hashlib + + from sos import _sos as _ + from sos import __version__ +@@ -658,6 +660,7 @@ class SoSReport(object): + self.tempfile_util = None + self._args = args + self.sysroot = "/" ++ self.sys_tmp = None + + try: + import signal +@@ -676,15 +679,22 @@ class SoSReport(object): + + self._is_root = self.policy.is_root() + +- self.tmpdir = os.path.abspath( +- self.policy.get_tmp_dir(self.opts.tmp_dir)) +- if not os.path.isdir(self.tmpdir) \ +- or not os.access(self.tmpdir, os.W_OK): ++ # system temporary directory to use ++ tmp = os.path.abspath(self.policy.get_tmp_dir(self.opts.tmp_dir)) ++ ++ if not os.path.isdir(tmp) \ ++ or not os.access(tmp, os.W_OK): + # write directly to stderr as logging is not initialised yet +- sys.stderr.write("temporary directory %s " % self.tmpdir ++ sys.stderr.write("temporary directory %s " % tmp + + "does not exist or is not writable\n") + self._exit(1) ++ ++ self.sys_tmp = tmp ++ ++ # our (private) temporary directory ++ self.tmpdir = tempfile.mkdtemp(prefix="sos.", dir=self.sys_tmp) + self.tempfile_util = TempFileUtil(self.tmpdir) ++ + self._set_directories() + + self._setup_logging() +@@ -1406,25 +1416,47 @@ class SoSReport(object): + raise + self._log_plugin_exception(plugname, "postproc") + ++ def _create_checksum(self, archive, hash_name): ++ if not archive: ++ return False ++ ++ archive_fp = open(archive, 'rb') ++ digest = hashlib.new(hash_name) ++ digest.update(archive_fp.read()) ++ archive_fp.close() ++ return digest.hexdigest() ++ ++ def _write_checksum(self, archive, hash_name, checksum): ++ # store checksum into file ++ fp = open(archive + "." + hash_name, "w") ++ if checksum: ++ fp.write(checksum + "\n") ++ fp.close() ++ + def final_work(self): +- # this must come before archive creation to ensure that log ++ # This must come before archive creation to ensure that log + # files are closed and cleaned up at exit. ++ # ++ # All subsequent terminal output must use print(). + self._finish_logging() +- # package up the results for the support organization ++ ++ archive = None # archive path ++ directory = None # report directory path (--build) ++ ++ # package up and compress the results + if not self.opts.build: + old_umask = os.umask(0o077) + if not self.opts.quiet: + print(_("Creating compressed archive...")) + # compression could fail for a number of reasons + try: +- final_filename = self.archive.finalize( ++ archive = self.archive.finalize( + self.opts.compression_type) + except (OSError, IOError) as e: + if e.errno in fatal_fs_errors: +- self.ui_log.error("") +- self.ui_log.error(" %s while finalizing archive" +- % e.strerror) +- self.ui_log.error("") ++ print("") ++ print(_(" %s while finalizing archive" % e.strerror)) ++ print("") + self._exit(1) + except: + if self.opts.debug: +@@ -1434,8 +1466,58 @@ class SoSReport(object): + finally: + os.umask(old_umask) + else: +- final_filename = self.archive.get_archive_path() +- self.policy.display_results(final_filename, build=self.opts.build) ++ # move the archive root out of the private tmp directory. ++ directory = self.archive.get_archive_path() ++ dir_name = os.path.basename(directory) ++ try: ++ os.rename(directory, os.path.join(self.sys_tmp, dir_name)) ++ except (OSError, IOError): ++ print(_("Error moving directory: %s" % directory)) ++ return False ++ ++ checksum = None ++ ++ if not self.opts.build: ++ # compute and store the archive checksum ++ hash_name = self.policy.get_preferred_hash_name() ++ checksum = self._create_checksum(archive, hash_name) ++ self._write_checksum(archive, hash_name, checksum) ++ ++ # output filename is in the private tmpdir - move it to the ++ # containing directory. ++ final_name = os.path.join(self.sys_tmp, os.path.basename(archive)) ++ ++ archive_hash = archive + "." + hash_name ++ final_hash = final_name + "." + hash_name ++ ++ # move the archive and checksum file ++ try: ++ os.rename(archive, final_name) ++ archive = final_name ++ except (OSError, IOError): ++ print(_("Error moving archive file: %s" % archive)) ++ return False ++ ++ # There is a race in the creation of the final checksum file: ++ # since the archive has already been published and the checksum ++ # file name is predictable once the archive name is known a ++ # malicious user could attempt to create a symbolic link in order ++ # to misdirect writes to a file of the attacker's choosing. ++ # ++ # To mitigate this we write the checksum inside the private tmp ++ # directory and use an atomic rename that is guaranteed to either ++ # succeed or fail: at worst the move will fail and be reported to ++ # the user. The correct checksum value is still written to the ++ # terminal and nothing is written to a location under the control ++ # of the user creating the link. ++ try: ++ os.rename(archive_hash, final_hash) ++ except (OSError, IOError): ++ print(_("Error moving checksum file: %s" % archive_hash)) ++ return False ++ ++ self.policy.display_results(archive, directory, checksum) ++ + self.tempfile_util.clean() + return True + +@@ -1490,8 +1572,10 @@ class SoSReport(object): + self.archive.cleanup() + if self.tempfile_util: + self.tempfile_util.clean() ++ if self.tmpdir: ++ rmtree(self.tmpdir) + except: +- pass ++ raise + + return False + +diff -up sos-3.2/sos/utilities.py.orig sos-3.2/sos/utilities.py +--- sos-3.2/sos/utilities.py.orig 2015-12-16 13:06:08.732706400 +0000 ++++ sos-3.2/sos/utilities.py 2015-12-16 13:07:09.455189249 +0000 +@@ -53,18 +53,6 @@ def fileobj(path_or_file, mode='r'): + 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_) +diff -up sos-3.2/tests/utilities_tests.py.orig sos-3.2/tests/utilities_tests.py +--- sos-3.2/tests/utilities_tests.py.orig 2015-12-16 13:06:57.512094280 +0000 ++++ sos-3.2/tests/utilities_tests.py 2015-12-16 13:07:09.455189249 +0000 +@@ -5,7 +5,7 @@ import unittest + import six + from six import StringIO + +-from sos.utilities import grep, get_hash_name, is_executable, sos_get_command_output, find, tail, shell_out ++from sos.utilities import grep, is_executable, sos_get_command_output, find, tail, shell_out + import sos + + TEST_DIR = os.path.dirname(__file__) diff --git a/sos-squid-collect-var-log-squid.patch b/sos-squid-collect-var-log-squid.patch new file mode 100644 index 0000000..0ad4c03 --- /dev/null +++ b/sos-squid-collect-var-log-squid.patch @@ -0,0 +1,32 @@ +From d0408ac43e1ec3b114e69b2950202f87f2fcd250 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Mon, 19 Jan 2015 18:12:15 +0000 +Subject: [PATCH] [squid] collect logs from /var/log/squid + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/squid.py | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/sos/plugins/squid.py b/sos/plugins/squid.py +index 0d596e5..f1aea73 100644 +--- a/sos/plugins/squid.py ++++ b/sos/plugins/squid.py +@@ -29,8 +29,12 @@ class RedHatSquid(Squid, RedHatPlugin): + packages = ('squid',) + + def setup(self): +- self.add_copy_spec_limit("/etc/squid/squid.conf", +- sizelimit=self.get_option('log_size')) ++ log_size = self.get_option('log_size') ++ log_path = "/var/log/squid/" ++ self.add_copy_spec_limit("/etc/squid/squid.conf", sizelimit=log_size) ++ self.add_copy_spec_limit(log_path + "access.log", sizelimit=log_size) ++ self.add_copy_spec_limit(log_path + "cache.log", sizelimit=log_size) ++ self.add_copy_spec_limit(log_path + "squid.out", sizelimit=log_size) + + + class DebianSquid(Squid, DebianPlugin, UbuntuPlugin): +-- +1.9.3 + diff --git a/sos-virsh-plugin.patch b/sos-virsh-plugin.patch new file mode 100644 index 0000000..e8c4536 --- /dev/null +++ b/sos-virsh-plugin.patch @@ -0,0 +1,131 @@ +From 5280e3c73894805662c831d1f6cadda8233cf402 Mon Sep 17 00:00:00 2001 +From: Pavel Moravec +Date: Fri, 3 Apr 2015 09:53:46 +0200 +Subject: [PATCH 1/3] [virsh] add new plugin + +Move the virsh commands and virt-manager logs into new plugin +(corresponding to the 'libvirt-client' package on Red Hat distros). + +Resolves #544 + +Signed-off-by: Pavel Moravec +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/virsh.py | 46 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 46 insertions(+) + create mode 100644 sos/plugins/virsh.py + +diff --git a/sos/plugins/virsh.py b/sos/plugins/virsh.py +new file mode 100644 +index 0000000..4b6bcc0 +--- /dev/null ++++ b/sos/plugins/virsh.py +@@ -0,0 +1,46 @@ ++# 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 LibvirtClient(Plugin, RedHatPlugin, UbuntuPlugin, DebianPlugin): ++ """client for libvirt virtualization API ++ """ ++ ++ plugin_name = 'virsh' ++ profiles = ('system', 'virt') ++ ++ packages = ('libvirt-client') ++ ++ def setup(self): ++ # virt-manager logs ++ if not self.get_option("all_logs"): ++ self.add_copy_spec_limit("/root/.virt-manager/*", sizelimit=5) ++ else: ++ self.add_copy_spec("/root/.virt-manager/*") ++ ++ # get lit of VMs/domains ++ domains_file = self.get_cmd_output_now('virsh list --all') ++ ++ # cycle through the VMs/domains list, ignore 2 header lines and latest ++ # empty line, and dumpxml domain name in 2nd column ++ if domains_file: ++ domains_lines = open(domains_file, "r").read().splitlines()[2:] ++ for domain in filter(lambda x: x, domains_lines): ++ self.add_cmd_output("virsh dumpxml %s" % domain.split()[1]) ++ ++# vim: et ts=4 sw=4 +-- +1.8.3.1 + + +From 60373759aaa9f0668f0200e000e6c1949334597b Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Tue, 30 Jun 2015 13:10:51 +0100 +Subject: [PATCH 2/3] [libvirt] add listing of /var/lib/libvirt/qemu + +Signed-off-by: Bryn M. Reeves +--- + sos/plugins/libvirt.py | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sos/plugins/libvirt.py b/sos/plugins/libvirt.py +index 8d5dcfc..0b31d31 100644 +--- a/sos/plugins/libvirt.py ++++ b/sos/plugins/libvirt.py +@@ -58,6 +58,8 @@ class Libvirt(Plugin, RedHatPlugin, UbuntuPlugin, DebianPlugin): + if os.path.exists(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 xmlfile in glob.glob("/etc/libvirt/qemu/*.xml"): + self.do_file_sub( +-- +1.8.3.1 + + +From 26fa7d3ae5a6c31030ac045aeaa32452ad888df8 Mon Sep 17 00:00:00 2001 +From: Pavel Moravec +Date: Fri, 15 May 2015 16:10:41 +0200 +Subject: [PATCH 3/3] [virsh] make dumpxml calls read-only and set timeout=180 + +Call virsh dumpxml in read-only mode to bypass authentication +and extend the command timeout to 180s. + +Resolves #544 + +Signed-off-by: Pavel Moravec +--- + sos/plugins/virsh.py | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/sos/plugins/virsh.py b/sos/plugins/virsh.py +index 4b6bcc0..0381b39 100644 +--- a/sos/plugins/virsh.py ++++ b/sos/plugins/virsh.py +@@ -41,6 +41,7 @@ class LibvirtClient(Plugin, RedHatPlugin, UbuntuPlugin, DebianPlugin): + if domains_file: + domains_lines = open(domains_file, "r").read().splitlines()[2:] + for domain in filter(lambda x: x, domains_lines): +- self.add_cmd_output("virsh dumpxml %s" % domain.split()[1]) ++ self.add_cmd_output("virsh -r dumpxml %s" % domain.split()[1], ++ timeout=180) + + # vim: et ts=4 sw=4 +-- +1.8.3.1 + diff --git a/sos.spec b/sos.spec index ed049bd..8629b41 100644 --- a/sos.spec +++ b/sos.spec @@ -1,21 +1,90 @@ -%global commit 55c89eb6810e7060845082845653b059aab90e3d -%global shortcommit %(c=%{commit}; echo ${c:0:7}) +%{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")} Summary: A set of tools to gather troubleshooting information from a system Name: sos Version: 3.2 -Release: 0.4.a%{?dist} +Release: 1%{?dist} Group: Applications/System -Source0: https://github.com/sosreport/sos/archive/%{commit}.tar.gz#/%{name}-%{commit}.tar.gz +Source0: https://github.com/sosreport/sos/archive/%{version}/sos-%{version}.tar.gz License: GPLv2+ BuildArch: noarch -Url: http://fedorahosted.org/sos -BuildRequires: python3-devel +Url: http://github.com/sosreport/sos +BuildRequires: python-devel BuildRequires: gettext -Requires: libxml2-python3 -Requires: rpm-python3 -Requires: tar +Requires: libxml2-python Requires: bzip2 Requires: xz +Obsoletes: sos-plugins-openstack +Patch0: sos-six-compat.patch +Patch1: sos-call-rhsm-debug-with-no-subscriptions.patch +Patch2: sos-powerpc-allow-powerpc-plugin-to-run-on-ppc64le.patch +Patch3: sos-ovirt_hosted_engine-fix-exception-when-force-enabled.patch +Patch4: sos-corosync-add-postprocessing-for-corosync-objctl.patch +Patch5: sos-add-support-for-tomcat7.patch +Patch6: sos-obtain-mysql-password-from-env.patch +Patch7: sos-sosreport-fix-archive-permissions-regression.patch +Patch8: sos-fix-kpatch-force-enabled.patch +Patch9: sos-disable-the-zip-compression-type.patch +Patch10: sos-navicli-catch-unreadable-stdin.patch +Patch11: sos-docs-update-man-page-for-new-options.patch +Patch12: sos-sos-unicode-use-errors-ignore.patch +Patch13: sos-mysql-fix-command-line-dbpass-handling.patch +Patch14: sos-anaconda-make-useradd-password-regex-tolerant.patch +Patch15: sos-sosreport-catch-oserror-in-execute.patch +Patch16: sos-sosreport-do-not-make-logging-calls-after-oserror.patch +Patch17: sos-plugin-limit-names-to-pc_name_max.patch +Patch18: sos-squid-collect-var-log-squid.patch +Patch19: sos-sosreport-log-plugin-exceptions-to-file.patch +Patch20: sos-ctdb-fix-redhatplugin-tagging-use.patch +Patch21: sos-sosreport-fix-silent-exception-handling.patch +Patch22: sos-mysql-test-for-boolean-values.patch +Patch23: sos-mysql-improve-dbuser-dbpass-handling.patch +Patch24: sos-cluster-crmreport-create-dir.patch +Patch25: sos-openstack-neutron-to-collect-neutron-folders.patch +Patch26: sos-ovirt-engine-remove-password-leak.patch +Patch27: sos-fix-exception-when-networkmanager-disabled.patch +Patch28: sos-openstack-sahara-plugin.patch +Patch29: sos-redact-secrets-from-sahara-config.patch +Patch30: sos-cluster-data-ownership.patch +Patch31: sos-sat6-capsule-debug.patch +Patch32: sos-httpd-collect-conf-modules.patch +Patch33: sos-pcp-collect-config.patch +Patch34: sos-puppet-collect-config.patch +Patch35: sos-parted-no-human-readable.patch +Patch36: sos-sos-ticket-number-name-params.patch +Patch37: sos-network-more-diagnostic.patch +Patch38: sos-infiniband-more-diagnostic.patch +Patch39: sos-rabbitmq-cluster-status.patch +Patch40: sos-networking-ip-addr.patch +Patch41: sos-kimchid-plugin.patch +Patch42: sos-iprconfig-plugin.patch +Patch43: sos-ovirt-engine-config-domain-list.patch +Patch44: sos-activemq-collect-logs-config.patch +Patch45: sos-cluster-enable-when-luci-only.patch +Patch46: sos-hpasm-no-data-timeout.patch +Patch47: sos-mariadb-mysql-add-log.patch +Patch48: sos-chrony-new-plugin.patch +Patch49: sos-cluster-crm-report-password-sanitize.patch +Patch50: sos-virsh-plugin.patch +Patch51: sos-sap-hana-netweaver-vhostmd-plugins.patch +Patch52: sos-sos-verify-profile-for-valid-plugins-only.patch +Patch53: sos-kernel-additional-diagnostic.patch +Patch54: sos-ceph-add-calamari-rados.patch +Patch55: sos-iprconfig-enable-on-ppc64le.patch +Patch56: sos-openstack_trove-plugin.patch +Patch57: sos-services-add-more-diagnostics.patch +Patch58: sos-openstack_neutron-obfuscate-passwords.patch +Patch59: sos-policies-PackageManager-timeout.patch +Patch60: sos-plugins-allow-discard-stderr.patch +Patch61: sos-sos-inside-container.patch +Patch62: sos-openstack-obfuscate-passwords-secrets.patch +Patch63: sos-openvswitch-collect-logs-db-bridges.patch +Patch64: sos-sapnw-cmd-output-check.patch +Patch65: sos-logs-plugin-traceback.patch +Patch66: sos-pick-up-symlink-targets.patch +Patch67: sos-html-report-generate.patch +Patch68: sos-collect-docker-daemon-logs.patch +Patch69: sos-ceph-collect-var-lib-var-run.patch +Patch70: sos-sosreport-prepare-report-in-a-private-subdirectory.patch %description Sos is a set of tools that gathers information about system @@ -24,8 +93,78 @@ diagnostic purposes and debugging. Sos is commonly used to help support technicians and developers. %prep -# deal with github tarball naming scheme -%setup -q -n %{name}-%{commit} +%setup -qn %{name}-%{version} +%patch0 -p1 +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 +%patch17 -p1 +%patch18 -p1 +%patch19 -p1 +%patch20 -p1 +%patch21 -p1 +%patch22 -p1 +%patch23 -p1 +%patch24 -p1 +%patch25 -p1 +%patch26 -p1 +%patch27 -p1 +%patch28 -p1 +%patch29 -p1 +%patch30 -p1 +%patch31 -p1 +%patch32 -p1 +%patch33 -p1 +%patch34 -p1 +%patch35 -p1 +%patch36 -p1 +%patch37 -p1 +%patch38 -p1 +%patch39 -p1 +%patch40 -p1 +%patch41 -p1 +%patch42 -p1 +%patch43 -p1 +%patch44 -p1 +%patch45 -p1 +%patch46 -p1 +%patch47 -p1 +%patch48 -p1 +%patch49 -p1 +%patch50 -p1 +%patch51 -p1 +%patch52 -p1 +%patch53 -p1 +%patch54 -p1 +%patch55 -p1 +%patch56 -p1 +%patch57 -p1 +%patch58 -p1 +%patch59 -p1 +%patch60 -p1 +%patch61 -p1 +%patch62 -p1 +%patch63 -p1 +%patch64 -p1 +%patch65 -p1 +%patch66 -p1 +%patch67 -p1 +%patch68 -p1 +%patch69 -p1 +%patch70 -p1 %build %{__python3} setup.py build @@ -46,6 +185,108 @@ install -Dm644 %{name}.conf %{buildroot}%{_sysconfdir}/%{name}.conf %config(noreplace) %{_sysconfdir}/sos.conf %changelog +* Wed Dec 16 2015 Bryn M. Reeves = 3.2-1 +- [global] sync rawhide package with upstream +- [ceph] collect /var/lib/ceph and /var/run/ceph +- [sosreport] prepare report in a private subdirectory (CVE-2015-7529) +- [docker] collect journald logs for docker unit +- [sosreport] fix command-line report defaults +- [openstack_neutron] obfuscate server_auth in restproxy.ini +- [memory] collect swapon --show output in bytes +- [sosreport] fix command-line report defaults (proper patch ordering) +- [sapnw] call self methods properly +- [openvswitch] capture the logs, db and OVS bridges details +- [logs] fix reference to missing 'rsyslog_conf' variable +- [sapnw] Add check if saphostctrl is not present, dont use Set +- [Plugin] fix handling of symlinks in non-sysroot environments +- [openstack] Ensure openstack passwords and secrets are obfuscated +- [plugin] pass stderr through _collect_cmd_output +- [kubernetes,plugin] Support running sos inside a container +- [openstack] New Openstack Trove (DBaaS) plugin +- [services] Add more diagnostics to applications +- [openstack_neutron] Obscure passwords and secrets +- [ceph] add calamari and ragos logs and configs +- [iprconfig] enable plugin for ppc64* architectures +- [general] verify --profile contains valid plugins only +- [kernel,mpt,memory] additional kernel-related diagnostics +- [cluster] enable crm_report password scrubbing +- [sosreport] fix command-line report defaults +- [virsh] add new plugin, add listing of qemu +- [sap*,vhostmd] new plugins for SAP +- [cluster] crm_report fails to run because dir already exists +- [foreman] Skip collection of generic resources +- [apache] Added collection of conf.modules.d dir for httpd 2.4 +- [pcp] collect /etc/pcp.conf +- [puppet] adding new plugin for puppet +- [block] Don't use parted human readable output +- [general] Better handling --name and --ticket-number in +- [networking] additional ip, firewall and traffic shaping +- [infiniband] add opensm and infiniband-diags support +- [plugins/rabbitmq] Added cluster_status command output +- [networking] re-add 'ip addr' with a root symlink +- [kimchi] add new plugin +- [iprconfig] add plugin for IBM Power RAID adapters +- [ovirt] Collect engine tunables and domain information. +- [activemq] Honour all_logs and get config on RHEL +- [cluster] Add luci to packages for standalone luci servers +- [hpasm] hpasmcli commands hang under timeout +- [mysql] Collect log file +- [chrony] add chrony plugin +- [openstack_sahara] redact secrets from sahara configuration +- [openstack_sahara] add new openstack_sahara plugin +- [openstack_neutron] neutron configuration and logs files not captured +- [ovirt] remove ovirt-engine setup answer file password leak +- [networking] network plugin fails if NetworkManager is disabled +- [cluster] crm_report fails to run because dir already exists +- [mysql] improve handling of dbuser, dbpass and MYSQL_PWD +- [mysql] test for boolean values in dbuser and dbpass +- [plugin] limit path names to PC_NAME_MAX +- [squid] collect files from /var/log/squid +- [sosreport] log plugin exceptions to a file +- [ctdb] fix collection of /etc/sysconfig/ctdb +- [sosreport] fix silent exception handling +- [sosreport] do not make logging calls after OSError +- [sosreport] catch OSError exceptions in SoSReport.execute() +- [anaconda] make useradd password regex tolerant of whitespace +- [mysql] fix handling of mysql.dbpass option +- [navicli] catch exceptions if stdin is unreadable +- [docs] update man page for new options +- [sosreport] make all utf-8 handling user errors=ignore +- [kpatch] do not attempt to collect data if kpatch is not installed +- [archive] drop support for Zip archives +- [sosreport] fix archive permissions regression +- [tomcat] add support for tomcat7 and default log size limits +- [mysql] obtain database password from the environment +- [corosync] add postprocessing for corosync-objctl output +- [ovirt_hosted_engine] fix exception when force-enabled +- [yum] call rhsm-debug with --no-subscriptions +- [powerpc] allow PowerPC plugin to run on ppc64le +- [package] add Obsoletes for sos-plugins-openstack +- [pam] add pam_tally2 and faillock support +- [postgresql] obtain db password from the environment +- [pcp] add Performance Co-Pilot plugin +- [nfsserver] collect /etc/exports.d +- [sosreport] handle --compression-type correctly +- [anaconda] redact passwords in kickstart configurations +- [haproxy] add new plugin +- [keepalived] add new plugin +- [lvm2] set locking_type=0 when calling lvm commands +- [tuned] add new plugin +- [cgroups] collect /etc/sysconfig/cgred +- [plugins] ensure doc text is always displayed for plugins +- [sosreport] fix the distribution version API call +- [docker] add new plugin +- [openstack_*] include broken-out openstack plugins +- [mysql] support MariaDB +- [openstack] do not collect /var/lib/nova +- [grub2] collect grub.cfg on UEFI systems +- [sosreport] handle out-of-space errors gracefully +- [firewalld] new plugin +- [networking] collect NetworkManager status +- [kpatch] new plugin +- [global] update to upstream 3.2 release +- [foreman] add new plugin + * Tue Nov 10 2015 Fedora Release Engineering - 3.2-0.4.a - Rebuilt for https://fedoraproject.org/wiki/Changes/python3.5 @@ -131,37 +372,37 @@ install -Dm644 %{name}.conf %{buildroot}%{_sysconfdir}/%{name}.conf * Thu Mar 20 2014 Bryn M. Reeves = 3.0-23 - Call rhsm-debug with the --sos switch -* Mon Mar 03 2014 Bryn M. Reeves = 3.0-22 +* Mon Mar 03 2014 Bryn M. Reeves - Fix package check in anacron plugin -* Wed Feb 12 2014 Bryn M. Reeves = 3.0-21 +* Wed Feb 12 2014 Bryn M. Reeves - Remove obsolete rhel_version() usage from yum plugin -* Tue Feb 11 2014 Bryn M. Reeves = 3.0-20 +* Tue Feb 11 2014 Bryn M. Reeves - Prevent unhandled exception during command output substitution -* Mon Feb 10 2014 Bryn M. Reeves = 3.0-19 +* Mon Feb 10 2014 Bryn M. Reeves - Fix generation of volume names in gluster plugin - Add distupgrade plugin -* Tue Feb 04 2014 Bryn M. Reeves = 3.0-18 +* Tue Feb 04 2014 Bryn M. Reeves - Prevent file descriptor leaks when using Popen - Disable zip archive creation when running rhsm-debug - Include volume geo-replication status in gluster plugin -* Mon Feb 03 2014 Bryn M. Reeves = 3.0-17 +* Mon Feb 03 2014 Bryn M. Reeves - Fix get_option use in cluster plugin - Fix debug logging to file when given '-v' - Always treat rhevm plugin's vdsmlogs option as a string - Run the rhsm-debug script from yum plugin -* Fri Jan 31 2014 Bryn M. Reeves = 3.0-16 +* Fri Jan 31 2014 Bryn M. Reeves - Add new plugin to collect OpenHPI configuration - Fix cluster plugin crm_report support - Fix file postprocessing in ldap plugin - Remove collection of anaconda-ks.cfg from general plugin -* Fri Jan 24 2014 Bryn M. Reeves = 3.0-15 +* Fri Jan 24 2014 Bryn M. Reeves - Remove debug statements from logs plugin - Make ethernet interface detection more robust - Fix specifying multiple plugin options on the command line @@ -170,45 +411,45 @@ install -Dm644 %{name}.conf %{buildroot}%{_sysconfdir}/%{name}.conf - Remove --upload command line option - Update sos UI text to match upstream -* Fri Dec 27 2013 Daniel Mach = 3.0-14 +* Fri Dec 27 2013 Daniel Mach - Mass rebuild 2013-12-27 -* Thu Nov 14 2013 Bryn M. Reeves = 3.0-13 +* Thu Nov 14 2013 Bryn M. Reeves - Fix regressions introduced with --build option -* Tue Nov 12 2013 Bryn M. Reeves = 3.0-12 +* Tue Nov 12 2013 Bryn M. Reeves - Fix typo in yum plug-in add_forbidden_paths - Add krb5 plug-in and drop collection of krb5.keytab -* Fri Nov 8 2013 Bryn M. Reeves = 3.0-10 +* Fri Nov 8 2013 Bryn M. Reeves - Add nfs client plug-in - Fix traceback when sar module force-enabled -* Thu Nov 7 2013 Bryn M. Reeves = 3.0-9 +* Thu Nov 7 2013 Bryn M. Reeves - Restore --build command line option - Collect saved vmcore-dmesg.txt files - Normalize temporary directory paths -* Tue Nov 5 2013 Bryn M. Reeves = 3.0-7 +* Tue Nov 5 2013 Bryn M. Reeves - Add domainname output to NIS plug-in - Collect /var/log/squid in squid plug-in - Collect mountstats and mountinfo in filesys plug-in - Add PowerPC plug-in from upstream -* Thu Oct 31 2013 Bryn M. Reeves = 3.0-6 +* Thu Oct 31 2013 Bryn M. Reeves - Remove version checks in gluster plug-in - Check for usable temporary directory - Fix --alloptions command line option - Fix configuration fail regression -* Wed Oct 30 2013 Bryn M. Reeves = 3.0-5 +* Wed Oct 30 2013 Bryn M. Reeves - Include /etc/yaboot.conf in boot plug-in - Fix collection of brctl output in networking plug-in - Verify limited set of RPM packages by default - Do not strip newlines from command output - Limit default sar data collection -* Thu Oct 3 2013 Bryn M. Reeves = 3.0-4 +* Thu Oct 3 2013 Bryn M. Reeves - Do not attempt to read RPC pseudo files in networking plug-in - Restrict wbinfo collection to the current domain - Add obfuscation of luci secrets to cluster plug-in @@ -217,39 +458,36 @@ install -Dm644 %{name}.conf %{buildroot}%{_sysconfdir}/%{name}.conf - Do not set batch mode if stdin is not a TTY - Attempt to continue when reading bad input in interactive mode -* Wed Aug 14 2013 Bryn M. Reeves = 3.0-3 +* Wed Aug 14 2013 Bryn M. Reeves - Add crm_report support to cluster plug-in - Fix rhel_version() usage in cluster and s390 plug-ins - Strip trailing newline from command output -* Sun Aug 04 2013 Fedora Release Engineering - 3.0-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild - -* Mon Jun 10 2013 Bryn M. Reeves = 3.0-2 +* Mon Jun 10 2013 Bryn M. Reeves - Silence 'could not run' messages at default verbosity - New upstream release -* Thu May 23 2013 Bryn M. Reeves = 2.2-39 +* Thu May 23 2013 Bryn M. Reeves - Always invoke tar with '-f-' option -* Mon Jan 21 2013 Bryn M. Reeves = 2.2-38 +* Mon Jan 21 2013 Bryn M. Reeves - Fix interactive mode regression when --ticket unspecified -* Fri Jan 18 2013 Bryn M. Reeves = 2.2-37 +* Fri Jan 18 2013 Bryn M. Reeves - Fix propagation of --ticket parameter in interactive mode -* Thu Jan 17 2013 Bryn M. Reeves = 2.2-36 +* Thu Jan 17 2013 Bryn M. Reeves - Revert OpenStack patch -* Wed Jan 9 2013 Bryn M. Reeves = 2.2-35 +* Wed Jan 9 2013 Bryn M. Reeves - Report --name and --ticket values as defaults - Fix device-mapper command execution logging - Fix data collection and rename PostreSQL module to pgsql -* Fri Oct 19 2012 Bryn M. Reeves = 2.2-34 +* Fri Oct 19 2012 Bryn M. Reeves - Add support for content delivery hosts to RHUI module -* Thu Oct 18 2012 Bryn M. Reeves = 2.2-33 +* Thu Oct 18 2012 Bryn M. Reeves - Add Red Hat Update Infrastructure module - Collect /proc/iomem in hardware module - Collect subscription-manager output in general module @@ -257,14 +495,14 @@ install -Dm644 %{name}.conf %{buildroot}%{_sysconfdir}/%{name}.conf - Fix exception in gluster module on non-gluster systems - Fix exception in psql module when dbname is not given -* Wed Oct 17 2012 Bryn M. Reeves = 2.2-32 +* Wed Oct 17 2012 Bryn M. Reeves - Collect /proc/pagetypeinfo in memory module - Strip trailing newline from command output - Add sanlock module - Do not collect archived accounting files in psacct module - Call spacewalk-debug from rhn module to collect satellite data -* Mon Oct 15 2012 Bryn M. Reeves = 2.2-31 +* Mon Oct 15 2012 Bryn M. Reeves - Avoid calling volume status when collecting gluster statedumps - Use a default report name if --name is empty - Quote tilde characters passed to shell in RPM module @@ -277,40 +515,40 @@ install -Dm644 %{name}.conf %{buildroot}%{_sysconfdir}/%{name}.conf - Fix error logging when calling external programs - Use ip instead of ifconfig to generate network interface lists -* Wed May 23 2012 Bryn M. Reeves = 2.2-29 +* Wed May 23 2012 Bryn M. Reeves - Collect the swift configuration directory in gluster module - Update IPA module and related plug-ins -* Fri May 18 2012 Bryn M. Reeves = 2.2-28 +* Fri May 18 2012 Bryn M. Reeves - Collect mcelog files in the hardware module -* Wed May 02 2012 Bryn M. Reeves = 2.2-27 +* Wed May 02 2012 Bryn M. Reeves - Add nfs statedump collection to gluster module -* Tue May 01 2012 Bryn M. Reeves = 2.2-26 +* Tue May 01 2012 Bryn M. Reeves - Use wildcard to match possible libvirt log paths -* Mon Apr 23 2012 Bryn M. Reeves = 2.2-25 +* Mon Apr 23 2012 Bryn M. Reeves - Add forbidden paths for new location of gluster private keys -* Fri Mar 9 2012 Bryn M. Reeves = 2.2-24 +* Fri Mar 9 2012 Bryn M. Reeves - Fix katello and aeolus command string syntax - Remove stray hunk from gluster module patch -* Thu Mar 8 2012 Bryn M. Reeves = 2.2-22 +* Thu Mar 8 2012 Bryn M. Reeves - Correct aeolus debug invocation in CloudForms module - Update gluster module for gluster-3.3 - Add additional command output to gluster module - Add support for collecting gluster configuration and logs -* Wed Mar 7 2012 Bryn M. Reeves = 2.2-19 +* Wed Mar 7 2012 Bryn M. Reeves - Collect additional diagnostic information for realtime systems - Improve sanitization of RHN user and case number in report name - Fix verbose output and debug logging - Add basic support for CloudForms data collection - Add support for Subscription Asset Manager diagnostics -* Tue Mar 6 2012 Bryn M. Reeves = 2.2-18 +* Tue Mar 6 2012 Bryn M. Reeves - Collect fence_virt.conf in cluster module - Fix collection of /proc/net directory tree - Gather output of cpufreq-info when present @@ -330,22 +568,22 @@ install -Dm644 %{name}.conf %{buildroot}%{_sysconfdir}/%{name}.conf - Do not accept embedded forward slashes in RHN usernames - Add new sunrpc module to collect rpcinfo for gluster systems -* Tue Nov 1 2011 Bryn M. Reeves = 2.2-17 +* Tue Nov 1 2011 Bryn M. Reeves - Do not collect subscription manager keys in general plugin -* Fri Sep 23 2011 Bryn M. Reeves = 2.2-16 +* Fri Sep 23 2011 Bryn M. Reeves - Fix execution of RHN hardware.py from hardware plugin - Fix hardware plugin to support new lsusb path -* Fri Sep 09 2011 Bryn M. Reeves = 2.2-15 +* Fri Sep 09 2011 Bryn M. Reeves - Fix brctl collection when a bridge contains no interfaces - Fix up2dateclient path in hardware plugin -* Mon Aug 15 2011 Bryn M. Reeves = 2.2-14 +* Mon Aug 15 2011 Bryn M. Reeves - Collect brctl show and showstp output - Collect nslcd.conf in ldap plugin -* Sun Aug 14 2011 Bryn M. Reeves = 2.2-11 +* Sun Aug 14 2011 Bryn M. Reeves - Truncate files that exceed specified size limit - Add support for collecting Red Hat Subscrition Manager configuration - Collect /etc/init on systems using upstart @@ -353,11 +591,11 @@ install -Dm644 %{name}.conf %{buildroot}%{_sysconfdir}/%{name}.conf - Collect ipv6 neighbour table in network module - Collect basic cgroups configuration data -* Sat Aug 13 2011 Bryn M. Reeves = 2.2-10 +* Sat Aug 13 2011 Bryn M. Reeves - Fix collection of data from LVM2 reporting tools in devicemapper plugin - Add /proc/vmmemctl collection to vmware plugin -* Fri Aug 12 2011 Bryn M. Reeves = 2.2-9 +* Fri Aug 12 2011 Bryn M. Reeves - Collect yum repository list by default - Add basic Infiniband plugin - Add plugin for scsi-target-utils iSCSI target @@ -366,44 +604,44 @@ install -Dm644 %{name}.conf %{buildroot}%{_sysconfdir}/%{name}.conf - Extend data collection by qpidd plugin - Add ethtool pause, coalesce and ring (-a, -c, -g) options to network plugin -* Thu Apr 07 2011 Bryn M. Reeves = 2.2-8 +* Thu Apr 07 2011 Bryn M. Reeves - Use sha256 for report digest when operating in FIPS mode -* Tue Apr 05 2011 Bryn M. Reeves = 2.2-7 +* Tue Apr 05 2011 Bryn M. Reeves - Fix parted and dumpe2fs output on s390 -* Fri Feb 25 2011 Bryn M. Reeves = 2.2-6 +* Fri Feb 25 2011 Bryn M. Reeves - Fix collection of chkconfig output in startup.py - Collect /etc/dhcp in dhcp.py plugin - Collect dmsetup ls --tree output in devicemapper.py - Collect lsblk output in filesys.py -* Thu Feb 24 2011 Bryn M. Reeves = 2.2-4 +* Thu Feb 24 2011 Bryn M. Reeves - Fix collection of logs and config files in sssd.py - Add support for collecting entitlement certificates in rhn.py -* Thu Feb 03 2011 Bryn M. Reeves = 2.2-3 +* Thu Feb 03 2011 Bryn M. Reeves - Fix cluster plugin dlm lockdump for el6 - Add sssd plugin to collect configuration and logs - Collect /etc/anacrontab in system plugin - Correct handling of redhat-release for el6 -* Thu Jul 29 2010 Adam Stokes = 2.2-2 +* Thu Jul 29 2010 Adam Stokes -* Thu Jun 10 2010 Adam Stokes = 2.2-0 +* Thu Jun 10 2010 Adam Stokes -* Wed Apr 28 2010 Adam Stokes = 2.1-0 +* Wed Apr 28 2010 Adam Stokes -* Mon Apr 12 2010 Adam Stokes = 2.0-0 +* Mon Apr 12 2010 Adam Stokes -* Tue Mar 30 2010 Adam Stokes = 1.9-3 +* Tue Mar 30 2010 Adam Stokes - fix setup.py to autocompile translations and man pages - rebase 1.9 -* Fri Mar 19 2010 Adam Stokes = 1.9-2 +* Fri Mar 19 2010 Adam Stokes - updated translations -* Thu Mar 04 2010 Adam Stokes = 1.9-1 +* Thu Mar 04 2010 Adam Stokes - version bump 1.9 - replaced compression utility with xz - strip threading/multiprocessing @@ -414,243 +652,8 @@ install -Dm644 %{name}.conf %{buildroot}%{_sysconfdir}/%{name}.conf - simple profiling - make use of xgettext as pygettext is deprecated -* Mon Jan 18 2010 Adam Stokes = 1.8-21 +* Mon Jan 18 2010 Adam Stokes - more sanitizing options for log files - rhbz fixes from RHEL version merged into trunk - progressbar update -* Tue Nov 19 2009 Adam Stokes = 1.8-20 -- dont copy unwanted files due to symlinks -- More plugin enhancements - -* Tue Nov 5 2009 Adam Stokes = 1.8-18 -- Option to enable selinux fixfiles check -- Start of replacing Thread module with multiprocessing -- Update translations -- More checks against conf file versus command line opts - -* Tue Sep 9 2009 Adam Stokes = 1.8-16 -- Update rh-upload-core to rh-upload and allows general files -- Fix cluster plugin with pwd mangling invalidating xml -- Cluster support detecting invalid fence_id and fence states -- Read variables from conf file - -* Thu Jul 23 2009 Adam Stokes = 1.8-14 -- resolves: rhbz512536 wrong group in spec file -- resolves: rhbz498398 A series of refactoring patches to sos -- resolves: rhbz501149 A series of refactoring patches to sos (2) -- resolves: rhbz503804 remove obsolete translation -- resolves: rhbz502455 tricking sosreport into rm -rf / -- resolves: rhbz501146 branding in fedora - -* Mon Jul 20 2009 Adam Stokes = 1.8-13 -- Add requirements for tar,bzip2 during minimal installs -- More merges from reports against RHEL version of plugins -- Remove unecessary definition of localdir in spec - -* Wed May 05 2009 Adam Stokes - 1.8-11 -- Remove all instances of sysrq -- Consistent macro usage in spec - -* Wed Feb 25 2009 Fedora Release Engineering - 1.8-10 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild - -* Mon Dec 29 2008 Adam Stokes - 1.8-5 -- removed source defines as python manifest handles this - -* Fri Dec 19 2008 Adam Stokes - 1.8-4 -- spec cleanup, fixed license, source -- reworked Makefile to build properly - -* Thu Oct 23 2008 Adam Stokes - 1.8-1 - -* Wed Nov 21 2007 Navid Sheikhol-Eslami - 1.8-0 -- selinux: always collect sestatus -- added many languages -- added --debug option which causes exceptions not to be trapped -- updated to sysreport-1.4.3-13.el5 -- ftp upload to dropbox with --upload -- cluster: major rewrite to support different versions of RHEL -- cluster: check rg_test for errors -- minor changes in various plug-ins (yum, networking, process, kernel) -- fixed some exceptions in threads which were not properly trapped -- veritas: don't run rpm -qa every time -- using rpm's python bindings instead of external binary -- corrected autofs and ldap plugin that were failing when debug option was not found in config file. -- implemented built-in checkdebug() that uses self.files and self.packages to make the decision -- missing binaries are properly detected now. -- better doExitCode handling -- fixed problem with rpm module intercepting SIGINT -- error when user specifies an invalid plugin or plugin option -- named: fixed indentation -- replaced isOptionEnabled() with getOption() -- tune2fs and fdisk were not always run against the correct devices/mountpoint -- added gpg key to package -- updated README with new svn repo and contributors -- updated manpage -- better signal handling -- caching of rpm -q outputs -- report filename includes rhnUsername if available -- report encryption via gpg and support pubkey -- autofs: removed redundant files -- filesys: better handling of removable devices -- added sosReadFile() returns a file's contents -- return after looping inside a directory -- collect udevinfo for each block device -- simply collect output of fdisk -l in one go -- handle sysreport invocation properly (warn if shell is interactive, otherwise spawn sysreport.legacy) -- progress bar don't show 100% until finished() is called -- now runs on RHEL3 as well (python 2.2) -- replaced commonPrefix() with faster code -- filesys: one fdisk -l for all -- selinux: collect fixfilex check output -- devicemapper: collect udevinfo for all block devices -- cluster: validate node names according to RFC 2181 -- systemtap: cleaned up and added checkenabled() method -- added kdump plugin -- added collection of /etc/inittab - -* Wed Aug 13 2007 Navid Sheikhol-Eslami - 1.7-8 -- added README.rh-upload-core - -* Mon Aug 13 2007 Navid Sheikhol-Eslami - 1.7-7 -- added extras/rh-upload-core script from David Mair - -* Mon Aug 9 2007 Navid Sheikhol-Eslami - 1.7-6 -- more language fixes -- added arabic, italian and french -- package prepared for release -- included sysreport as sysreport.legacy - -* Mon Aug 9 2007 Navid Sheikhol-Eslami - 1.7-5 -- package obsoletes sysreport and creates a link pointing to sosreport -- added some commands in cluster and process plugins -- fixed html output (wrong links to cmds, thanks streeter) -- process: back down sleep if D state doesn't change - -* Mon Aug 1 2007 Navid Sheikhol-Eslami - 1.7-4 -- catch KeyboardInterrupt when entering sosreport name -- added color output for increased readability -- list was sorted twice, removing latter .sort() - -* Mon Jul 31 2007 Navid Sheikhol-Eslami - 1.7-3 -- added preliminary problem diagnosis support -- better i18n initialization -- better user messages -- more progressbar fixes -- catch and log python exceptions in report -- use python native commands to create symlinks -- limit concurrent running threads - -* Mon Jul 28 2007 Navid Sheikhol-Eslami - 1.7-2 -- initial language localization support -- added italian translation - -* Mon Jul 16 2007 Navid Sheikhol-Eslami - 1.7-1 -- split up command outputs in sub-directories (sos_command/plugin/command instead of sos_command/plugin.command) -- fixed doExitCode() calling thread.wait() instead of join() -- curses menu is disabled by default -- multithreading is enabled by default -- major progressbar changes (now has ETA) -- multithreading fixes -- plugins class descriptions shortened to fix better in --list-plugins -- rpm -Va in plugins/rpm.py sets eta_weight to 200 (plugin 200 longer than other plugins, for ETA calculation) -- beautified command output filenames in makeCommandFilename() - -* Mon Jul 12 2007 Navid Sheikhol-Eslami - 1.7-0 -- curses menu disabled by default (enable with -c) -- sosreport output friendlier to the user (and similar to sysreport) -- smarter plugin listing which also shows options and disable/enabled plugins -- require root permissions only for actual sosreport generation -- fix in -k where option value was treated as string instead of int -- made progressbar wider (60 chars) -- selinux plugin is enabled only if selinux is also enabled on the system -- made some errors less verbose to the user -- made sosreport not copy files pointed by symbolic links (same as sysreport, we don't need /usr/bin/X or /sbin/ifup) -- copy links as links (cp -P) -- added plugin get_description() that returns a short decription for the plugin -- guess sosreport name from system's name - -* Mon Jul 5 2007 Navid Sheikhol-Eslami - 1.6-5 -- Yet more fixes to make package Fedora compliant. - -* Mon Jul 5 2007 Navid Sheikhol-Eslami - 1.6-4 -- More fixes to make package Fedora compliant. - -* Mon Jul 2 2007 Navid Sheikhol-Eslami - 1.6-3 -- Other fixes to make package Fedora compliant. - -* Mon Jul 2 2007 Navid Sheikhol-Eslami - 1.6-2 -- Minor fixes. - -* Mon Jul 2 2007 Navid Sheikhol-Eslami - 1.6-1 -- Beautified output of --list-plugins. -- GPL licence is now included in the package. -- added python-devel requirement for building package - -* Fri May 25 2007 Steve Conklin - 1.5-1 -- Bumped version - -* Fri May 25 2007 Steve Conklin - 1.4-2 -- Fixed a backtrace on nonexistent file in kernel plugin (thanks, David Robinson) - -* Mon Apr 30 2007 Steve Conklin - 1.4-1 -- Fixed an error in option handling -- Forced the file generated by traceroute to not end in .com -- Fixed a problem with manpage -- Added optional traceroute collection to networking plugin -- Added clalance's patch to gather iptables info. -- Fixes to the device-mapper plugin -- Fixed a problem with installation of man page - -* Mon Apr 16 2007 Steve Conklin - 1.3-3 -- including patches to fix the following: - -* Tue Feb 20 2007 John Berninger - 1.3-2 -- Add man page - -* Fri Dec 15 2006 Steve Conklin - 1.3-1 -- really fixed bz_219654 - -* Fri Dec 15 2006 Steve Conklin - 1.2-1 -- fixed a build problem - -* Fri Dec 15 2006 Steve Conklin - 1.1-1 -- Tighten permissions of tmp directory so only readable by creator bz_219657 -- Don't print message 'Problem at path ...' bz_219654 -- Removed useless message bz_219670 -- Preserve file modification times bz_219674 -- Removed unneeded message about files on copyProhibitedList bz_219712 - -* Wed Aug 30 2006 Steve Conklin - 1.0-1 -- Seperated upstream and RPM versioning - -* Mon Aug 21 2006 Steve Conklin - 0.1-11 -- Code cleanup, fixed a regression in threading - -* Mon Aug 14 2006 Steve Conklin - 0.1-10 -- minor bugfixes, added miltithreading option, setup now quiet - -* Mon Jul 17 2006 Steve Conklin - 0.1-9 -- migrated to svn on 108.redhat.com, fixed a problem with command output linking in report - -* Mon Jun 19 2006 Steve Conklin - 0.1-6 -- Added LICENSE file containing GPL - -* Wed May 31 2006 Steve Conklin - 0.1-5 -- Added fixes to network plugin and prepped for Fedora submission - -* Wed May 31 2006 John Berninger - 0.1-4 -- Reconsolidated subpackages into one package per discussion with sconklin - -* Mon May 22 2006 John Berninger - 0.1-3 -- Added ftp, ldap, mail, named, samba, squid SOS plugins -- Fixed various errors in kernel and hardware plugins - -* Mon May 22 2006 John Benringer - 0.1-2 -- split off cluster plugin into subpackage -- correct file payload lists - -* Mon May 22 2006 John Berninger - 0.1-1 -- initial package build -