aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Makefile34
-rw-r--r--src/README23
-rw-r--r--src/setup.py78
-rw-r--r--src/sos.spec86
-rwxr-xr-xsrc/sosreport347
-rw-r--r--src/sosreport.116
6 files changed, 431 insertions, 153 deletions
diff --git a/src/Makefile b/src/Makefile
index 942e4776..37c384bc 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -59,7 +59,7 @@ release: clean
@echo " "
@echo "The final archive is ./$(NAME)-$(VERSION).tar.bz2."
-install:mo
+install:mo gpgkey
python setup.py install
@rm -rf build/lib
@@ -67,18 +67,40 @@ version:
@echo "The version is $(NAME)-$(VERSION)"
clean:
- @rm -fv *~ .*~ changenew ChangeLog.old $(NAME)-$(VERSION).tar.bz2 sosreport.1.gz
+ @rm -fv *~ .*~ changenew ChangeLog.old $(NAME)-$(VERSION).tar.bz2 sosreport.1.gz gpgkeys/rhsupport.*
@rm -rfv build/*
-rpm: mo
- @test -f sos.spec
+internal-rpm: gpgkey
+ @test -f sos-internal.spec
+ @mkdir -p $(TOPDIR)/SOURCES $(TOPDIR)/SRPMS $(TOPDIR)/RPMS $(TOPDIR)/BUILD $(SRCDIR)/dist
+ cp gpgkeys/rhsupport.pub gpgkeys/rhsupport.key $(TOPDIR)/SOURCES
+
+# this builds an RPM from the current working copy
+ @cd $(TOPDIR)/BUILD ; \
+ rm -rf $(NAME)-$(VERSION) ; \
+ ln -s $(SRCDIR) $(NAME)-$(VERSION) ; \
+ tar --gzip --exclude=.svn --exclude=svn-commit.tmp --exclude=$(NAME)-$(VERSION)/build --exclude=$(NAME)-$(VERSION)/dist \
+ --exclude gpgkeys/rhsupport.pub --exclude gpgkeys/rhsupport.key \
+ -chSpf $(TOPDIR)/SOURCES/$(NAME)-$(VERSION).tar.gz $(NAME)-$(VERSION) ; \
+ rm -f $(NAME)-$(VERSION)
+
+ rpmbuild -ba --define="_topdir $(TOPDIR)" sos-internal.spec
+ @mv $(TOPDIR)/RPMS/noarch/$(NAME)-internal-*.rpm $(TOPDIR)/SRPMS/$(NAME)-internal-*.rpm dist/
+ cp gpgkeys/rhsupport.key dist/
+
+rpm: mo gpgkey
@mkdir -p $(TOPDIR)/SOURCES $(TOPDIR)/SRPMS $(TOPDIR)/RPMS $(TOPDIR)/BUILD $(SRCDIR)/dist
+ cp gpgkeys/rhsupport.pub $(TOPDIR)/SOURCES
+
+ @test -f sos.spec
+
# this builds an RPM from the current working copy
@cd $(TOPDIR)/BUILD ; \
rm -rf $(NAME)-$(VERSION) ; \
ln -s $(SRCDIR) $(NAME)-$(VERSION) ; \
tar --gzip --exclude=.svn --exclude=svn-commit.tmp --exclude=$(NAME)-$(VERSION)/build --exclude=$(NAME)-$(VERSION)/dist \
+ --exclude gpgkeys/rhsupport.pub --exclude gpgkeys/rhsupport.key \
-chSpf $(TOPDIR)/SOURCES/$(NAME)-$(VERSION).tar.gz $(NAME)-$(VERSION) ; \
rm -f $(NAME)-$(VERSION)
@@ -95,3 +117,7 @@ pot:
mo:
find locale/*/LC_MESSAGES -name sos.po -exec python tools/msgfmt.py {} \;
+
+gpgkey:
+ @test -f gpgkeys/rhsupport.pub && echo "GPG key already exists." || \
+ gpg --batch --gen-key gpgkeys/gpg.template
diff --git a/src/README b/src/README
index 8d49ff35..808b8572 100644
--- a/src/README
+++ b/src/README
@@ -4,8 +4,8 @@ package maintainers, and anyone else to provide plugins that will
collect, analyze, and report information that is useful for supporting
software packages.
-This project is hosted at http://sos.108.redhat.com. For the latest version,
-to contribute, and for more information, please visit there.
+This project is hosted at http://hosted.fedoraproject.org/projects/sos
+For the latest version, to contribute, and for more information, please visit there.
To access to the public source code repository for this project run:
@@ -20,9 +20,20 @@ Maintainer:
Navid Sheikhol-Eslami <navid@redhat.com>
-Contributors:
+Developers and Contributors:
- Steve Conklin <sconklin@redhat.com>
- Pierre Amadio <pamadio@redhat.com>
+ Adam Stokes <astokes@redhat.com>
+ Cris Lalancette <clalance@redhat.com>
+ Eugene Teo <eteo@redhat.com>
John Berninger <jwb@redhat.com>
- Navid Sheikhol-Eslami <navid@redhat.com>
+ Justin Payne <jpayne@redhat.com>
+ Pierre Amadio <pamadio@redhat.com>
+ Qian Shen <qshen@redhat.com>
+ Steve Conklin <sconklin@redhat.com>
+
+Thanks to:
+
+ Eva Schaller <eschaller@redhat.com> for providing an Italian translation
+ Marco Ceci <mceci@redhat.com> for helping me out with the cluster plugin
+ Leonardo Macchia <lmacchia@redhat.com> for being my personal regexp generator
+ Imed Chihi <ichihi@redhat.com> for providing Arabic and French translations
diff --git a/src/setup.py b/src/setup.py
index b64c3593..d34ae6c8 100644
--- a/src/setup.py
+++ b/src/setup.py
@@ -9,6 +9,82 @@ setup(
packages = ['sos', 'sos.plugins'],
scripts = [],
package_dir = {'': 'lib',},
- data_files = [ ('/usr/sbin', ['sosreport', 'extras/sysreport/sysreport.legacy']), ('/usr/bin', ['extras/rh-upload-core']), ('/usr/share/sysreport', ['extras/sysreport/text.xsl', 'extras/sysreport/functions', 'extras/sysreport/sysreport-fdisk']), ('/usr/share/man/man1', ['sosreport.1']), ('/usr/share/locale/en', []), ('/usr/share/locale/it', []), ('/usr/share/locale/en/LC_MESSAGES', ['locale/en/LC_MESSAGES/sos.mo']), ('/usr/share/locale/it/LC_MESSAGES', ['locale/it/LC_MESSAGES/sos.mo']), ('/usr/share/locale/fr/LC_MESSAGES', ['locale/fr/LC_MESSAGES/sos.mo']), ('/usr/share/locale/ar/LC_MESSAGES', ['locale/ar/LC_MESSAGES/sos.mo'])
+ data_files = [ ('/etc', [ 'sos.conf']), ('/usr/sbin', ['sosreport', 'extras/sysreport/sysreport.legacy']), ('/usr/bin', ['extras/rh-upload-core']), ('/usr/share/sysreport', ['extras/sysreport/text.xsl', 'extras/sysreport/functions', 'extras/sysreport/sysreport-fdisk']), ('/usr/share/man/man1', ['sosreport.1']),
+ ('/usr/share/locale/af/LC_MESSAGES', ['locale/af/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/am/LC_MESSAGES', ['locale/am/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/ar/LC_MESSAGES', ['locale/ar/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/as/LC_MESSAGES', ['locale/as/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/be/LC_MESSAGES', ['locale/be/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/bg/LC_MESSAGES', ['locale/bg/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/bn/LC_MESSAGES', ['locale/bn/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/bn_IN/LC_MESSAGES', ['locale/bn_IN/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/bs/LC_MESSAGES', ['locale/bs/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/ca/LC_MESSAGES', ['locale/ca/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/cs/LC_MESSAGES', ['locale/cs/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/cy/LC_MESSAGES', ['locale/cy/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/da/LC_MESSAGES', ['locale/da/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/de/LC_MESSAGES', ['locale/de/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/el/LC_MESSAGES', ['locale/el/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/en/LC_MESSAGES', ['locale/en/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/en_GB/LC_MESSAGES', ['locale/en_GB/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/es/LC_MESSAGES', ['locale/es/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/et/LC_MESSAGES', ['locale/et/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/eu_ES/LC_MESSAGES', ['locale/eu_ES/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/fa/LC_MESSAGES', ['locale/fa/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/fi/LC_MESSAGES', ['locale/fi/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/fr/LC_MESSAGES', ['locale/fr/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/gl/LC_MESSAGES', ['locale/gl/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/gu/LC_MESSAGES', ['locale/gu/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/he/LC_MESSAGES', ['locale/he/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/hi/LC_MESSAGES', ['locale/hi/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/hr/LC_MESSAGES', ['locale/hr/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/hu/LC_MESSAGES', ['locale/hu/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/hy/LC_MESSAGES', ['locale/hy/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/id/LC_MESSAGES', ['locale/id/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/ilo/LC_MESSAGES', ['locale/ilo/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/is/LC_MESSAGES', ['locale/is/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/it/LC_MESSAGES', ['locale/it/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/ja/LC_MESSAGES', ['locale/ja/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/ka/LC_MESSAGES', ['locale/ka/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/kn/LC_MESSAGES', ['locale/kn/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/ko/LC_MESSAGES', ['locale/ko/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/ku/LC_MESSAGES', ['locale/ku/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/lo/LC_MESSAGES', ['locale/lo/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/lt/LC_MESSAGES', ['locale/lt/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/lv/LC_MESSAGES', ['locale/lv/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/mk/LC_MESSAGES', ['locale/mk/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/ml/LC_MESSAGES', ['locale/ml/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/mr/LC_MESSAGES', ['locale/mr/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/ms/LC_MESSAGES', ['locale/ms/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/my/LC_MESSAGES', ['locale/my/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/nb/LC_MESSAGES', ['locale/nb/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/nl/LC_MESSAGES', ['locale/nl/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/nn/LC_MESSAGES', ['locale/nn/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/no/LC_MESSAGES', ['locale/no/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/nso/LC_MESSAGES', ['locale/nso/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/or/LC_MESSAGES', ['locale/or/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/pa/LC_MESSAGES', ['locale/pa/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/pl/LC_MESSAGES', ['locale/pl/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/pt/LC_MESSAGES', ['locale/pt/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/pt_BR/LC_MESSAGES', ['locale/pt_BR/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/ro/LC_MESSAGES', ['locale/ro/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/ru/LC_MESSAGES', ['locale/ru/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/si/LC_MESSAGES', ['locale/si/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/sk/LC_MESSAGES', ['locale/sk/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/sl/LC_MESSAGES', ['locale/sl/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/sq/LC_MESSAGES', ['locale/sq/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/sr/LC_MESSAGES', ['locale/sr/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/sr@latin/LC_MESSAGES', ['locale/sr@latin/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/sv/LC_MESSAGES', ['locale/sv/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/ta/LC_MESSAGES', ['locale/ta/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/te/LC_MESSAGES', ['locale/te/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/th/LC_MESSAGES', ['locale/th/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/tr/LC_MESSAGES', ['locale/tr/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/uk/LC_MESSAGES', ['locale/uk/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/ur/LC_MESSAGES', ['locale/ur/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/vi/LC_MESSAGES', ['locale/vi/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/zh_CN/LC_MESSAGES', ['locale/zh_CN/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/zh_TW/LC_MESSAGES', ['locale/zh_TW/LC_MESSAGES/sos.mo']),
+ ('/usr/share/locale/zu/LC_MESSAGES', ['locale/zu/LC_MESSAGES/sos.mo']),
]
)
diff --git a/src/sos.spec b/src/sos.spec
index 0a0d8add..3b3f8534 100644
--- a/src/sos.spec
+++ b/src/sos.spec
@@ -1,8 +1,8 @@
%{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
%define name sos
-%define version 1.7
-%define release 9
+%define version 1.8
+%define release 0pre2
%define _localedir %_datadir/locale
@@ -10,19 +10,23 @@ Summary: A set of tools to gather troubleshooting information from a system
Name: %{name}
Version: %{version}
Release: %{release}%{?dist}
+Group: Application/Tools
# The source for this package was pulled from upstream's svn. Use the
# following commands to generate the tarball:
# svn --username guest export https://sos.108.redhat.com/svn/sos/tags/r1-7 sos-1.7
# tar -czvf sos-1.7.tar.gz sos-1.7
Source0: %{name}-%{version}.tar.gz
+Source1: rhsupport.pub
License: GPL
-Group: Development/Libraries
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot
BuildArch: noarch
-Url: http://sos.108.redhat.com/
+Url: https://hosted.fedoraproject.org/projects/sos
BuildRequires: python-devel
Requires: libxml2-python
+%if 0%{?rhel}
+Provides: sysreport = 1.4.3-13
Obsoletes: sysreport
+%endif
%description
Sos is a set of tools that gathers information about system
@@ -38,8 +42,18 @@ python setup.py build
%install
rm -rf ${RPM_BUILD_ROOT}
+install -D -m644 %{SOURCE1} ${RPM_BUILD_ROOT}/usr/share/sos/rhsupport.pub
python setup.py install --optimize 1 --root=$RPM_BUILD_ROOT
+
+%if 0%{?rhel}
ln -s /usr/sbin/sosreport $RPM_BUILD_ROOT/usr/sbin/sysreport
+%endif
+%if ! 0%{?rhel}
+rm -f $RPM_BUILD_ROOT/usr/sbin/sysreport.legacy
+rm -f $RPM_BUILD_ROOT/usr/share/sysreport/functions
+rm -f $RPM_BUILD_ROOT/usr/share/sysreport/sysreport-fdisk
+rm -f $RPM_BUILD_ROOT/usr/share/sysreport/text.xsl
+%endif
%clean
rm -rf ${RPM_BUILD_ROOT}
@@ -47,20 +61,76 @@ rm -rf ${RPM_BUILD_ROOT}
%files
%defattr(-,root,root,-)
%{_sbindir}/sosreport
+/usr/share/sos/rhsupport.pub
/usr/bin/rh-upload-core
+%if 0%{?rhel}
/usr/sbin/sysreport
/usr/sbin/sysreport.legacy
/usr/share/sysreport
+%endif
%{python_sitelib}/sos/
%{_mandir}/man1/sosreport.1*
%{_localedir}/*/LC_MESSAGES/sos.mo
%doc README README.rh-upload-core TODO LICENSE ChangeLog
+%config /etc/sos.conf
%changelog
-* Thu Aug 16 2007 Navid Sheikhol-Eslami <navid at redhat dot com> - 1.7-9
-- corrected a problem causing sometimes exceptions not to be catched when triggered within a thread
-
-* Mon Aug 13 2007 Navid Sheikhol-Eslami <navid at redhat dot com> - 1.7-8
+* Wed Nov 21 2007 Navid Sheikhol-Eslami <navid at redhat dot com> - 1.8-0
+- Resolves: bz368261 sosGetCommandOutput() does not block on hung processes
+- Resolves: bz361861 work-around missing traceback.format_exc() in RHEL4
+- Resolves: bz394781 device-mapper: use /sbin/lvm_dump to collect dm related info
+- Resolves: bz386691 unattended --batch option
+- Resolves: bz371251 sos could hang when accessing /sys/hypervisor/uuid
+- 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
+- Resolves: bz238778 added lspci -t
+- 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
+- Resolves: bz332151 apply regex to case number in sysreport for RHEL4
+- Resolves: bz332211 apply regex to case number in sysreport for RHEL5
+- Resolves: bz400111 sos incorrectly reports cluster data in SMP machine
+
+* Wed Aug 13 2007 Navid Sheikhol-Eslami <navid at redhat dot com> - 1.7-8
- added README.rh-upload-core
* Mon Aug 13 2007 Navid Sheikhol-Eslami <navid at redhat dot com> - 1.7-7
diff --git a/src/sosreport b/src/sosreport
index 888e0b54..516cda22 100755
--- a/src/sosreport
+++ b/src/sosreport
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
"""
Gather information about a system and report it using plugins
supplied for application-specific information
@@ -28,19 +28,26 @@ supplied for application-specific information
import sys
import os
from optparse import OptionParser, Option
+import ConfigParser
import sos.policyredhat
from sos.helpers import *
from snack import *
from threading import Thread, activeCount
import signal
-import logging
from stat import *
from time import strftime, localtime, time
from pwd import getpwuid
import gettext
from threading import Semaphore
-__version__ = 1.7
+# RHEL3 doesn't have a logging module
+try:
+ import logging
+except ImportError:
+ import sos.rhel3_logging
+ logging = sos.rhel3_logging
+
+__version__ = 1.8
__breakHits__ = 0 # Use this to track how many times we enter the exit routine
@@ -50,10 +57,15 @@ def exittermhandler(signum, frame):
def doExitCode():
from threading import enumerate
- global __breakHits__
+ global __breakHits__, loadedplugins, dstroot
+
__breakHits__ += 1
if ( ( activeCount() > 1 ) and ( __breakHits__ == 1 ) ):
print "SIGTERM received, multiple threads detected, waiting for all threads to exit"
+
+ for plugname, plug in loadedplugins:
+ plug.exit_please()
+
for thread in enumerate():
if thread.getName() == "MainThread":
continue
@@ -62,20 +74,41 @@ def doExitCode():
try:
thread.join()
except KeyboardInterrupt:
- pass
+ doExitCode()
else:
print "All threads ended, cleaning up."
- if ( ( activeCount() > 1 ) and ( __breakHits__ > 1 ) ):
- print "Multiple SIGTERMs, multiple threads, attempting to signal threads to die immediately"
+ doExit(1)
+
+ if ( ( activeCount() > 1 ) and ( __breakHits__ > 1 ) ):
+ print "Multiple SIGTERMs, multiple threads, attempting to signal threads to die immediately."
## FIXME: Add thread-kill code (see FIXME below)
-# os.kill(os.getpid(), signal.SIGKILL)
- print "Threads dead, cleaning up."
- if ( ( activeCount() == 1 ) and ( __breakHits__ > 2 ) ):
+ return
+ elif ( ( activeCount() > 1 ) and ( __breakHits__ > 2 ) ):
+ print "Multiple SIGTERMs, multiple threads, process suicides."
+ os.kill(os.getpid(), signal.SIGKILL)
+ elif ( ( activeCount() == 1 ) and ( __breakHits__ > 2 ) ):
print "Multiple SIGTERMs, single thread, exiting without cleaning up."
- sys.exit(3)
-
- # FIXME: Add code here to clean up /tmp
- sys.exit("Abnormal exit")
+ doExit(3)
+
+ doExit("Abnormal exit")
+
+def doExit(error=0):
+ global policy
+ policy.cleanDstroot()
+ sys.exit(error)
+
+def doException(type, value, tb):
+ if hasattr(sys, 'ps1') or not sys.stderr.isatty():
+ # we are in interactive mode or we don't have a tty-like
+ # device, so we call the default hook
+ sys.__excepthook__(type, value, tb)
+ else:
+ import traceback, pdb
+ # we are NOT in interactive mode, print the exception...
+ traceback.print_exception(type, value, tb)
+ print
+ # ...then start the debugger in post-mortem mode.
+ pdb.pm()
# Handle any sort of exit signal cleanly
# Currently, we intercept only sig 15 (TERM)
@@ -84,9 +117,6 @@ signal.signal(signal.SIGTERM, exittermhandler)
## FIXME: Need to figure out how to IPC with child threads in case of
## multiple SIGTERMs.
-# for debugging
-__raisePlugins__ = 0
-
class OptionParser_extended(OptionParser):
def print_help(self):
OptionParser.print_help(self)
@@ -95,10 +125,10 @@ class OptionParser_extended(OptionParser):
print
print " enable cluster plugin only and collect dlm lockdumps:"
print " # sosreport -o cluster -k cluster.lockdump"
- print
+ print
print " disable memory and samba plugins, turn off rpm -Va collection:"
print " # sosreport -n memory,samba -k rpm.rpmva=off"
- print
+ print
class SosOption (Option):
"""Allow to specify comma delimited list of plugins"""
@@ -133,43 +163,55 @@ __cmdParser__.add_option("-k", action="extend", \
__cmdParser__.add_option("-a", "--alloptions", action="store_true", \
dest="usealloptions", default=False, \
help="enable all options for loaded plugins")
+__cmdParser__.add_option("-u", "--upload", action="store_true", \
+ dest="upload", default=False, \
+ help="upload the report to Red Hat support")
+#__cmdParser__.add_option("--encrypt", action="store_true", \
+# dest="encrypt", default=False, \
+# help="encrypt with GPG using Red Hat support's public key")
+__cmdParser__.add_option("--batch", action="store_true", \
+ dest="batch", default=False, \
+ help="do not ask any question (batch mode)")
+__cmdParser__.add_option("--no-colors", action="store_true", \
+ dest="nocolors", default=False, \
+ help="do not use terminal colors for text")
__cmdParser__.add_option("-v", "--verbose", action="count", \
dest="verbosity", \
help="increase verbosity")
+__cmdParser__.add_option("--debug", action="count", \
+ dest="debug", \
+ help="enabling debugging")
__cmdParser__.add_option("--no-progressbar", action="store_false", \
dest="progressbar", default=True, \
help="do not display a progress bar.")
__cmdParser__.add_option("--no-multithread", action="store_true", \
dest="nomultithread", \
help="disable multi-threaded gathering mode (slower)", default=False)
-__cmdParser__.add_option("--name", action="store", \
- dest="name",type="string", \
- help="first initial and last name.", default="")
-__cmdParser__.add_option("--ticket-number", action="store", \
- dest="ticketnumber", type="string", \
- help="ticket number.", default="")
if sys.argv[0].endswith("sysreport"):
- try:
- ppid = os.getppid()
- fp = open("/proc/%d/cmdline" % ppid, "r")
- cmd = fp.read()
- fp.close()
- except:
- cmd = ""
- if not sys.stdin.isatty() or cmd.find("bash") < 0:
- os.execl("/bin/sh", "/bin/sh", "-c", "/usr/sbin/sysreport.legacy")
- os.exit(-1)
print
print "WARNING: sysreport is deprecated, please use sosreport instead."
+ if not sys.stdin.isatty():
+ print
+ os.execl("/bin/sh", "/bin/sh", "-c", "/usr/sbin/sysreport.legacy")
+ sys.exit(-1)
+
+if "-norpm" in sys.argv:
+ print
+ print """WARNING: sysreport's "-norpm" option is deprecated, please use "-k rpm.rpmva=off" instead."""
+ print
+ sys.exit(1)
(__cmdLineOpts__, __cmdLineArgs__)=__cmdParser__.parse_args()
def textcolor(text, fg, raw=0):
+ global __cmdLineOpts__
+ if __cmdLineOpts__.nocolors:
+ return text
colors = { "black":"30", "red":"31", "green":"32", "brown":"33", "blue":"34",
- "purple":"35", "cyan":"36", "lgray":"37", "gray":"1;30", "lred":"1;31",
- "lgreen":"1;32", "yellow":"1;33", "lblue":"1;34", "pink":"1;35",
- "lcyan":"1;36", "white":"1;37" }
+ "purple":"35", "cyan":"36", "lgray":"37", "gray":"1;30", "lred":"1;31",
+ "lgreen":"1;32", "yellow":"1;33", "lblue":"1;34", "pink":"1;35",
+ "lcyan":"1;36", "white":"1;37" }
opencol = "\033["
closecol = "m"
clear = opencol + "0" + closecol
@@ -188,11 +230,11 @@ class progressBar:
self.last_amount_update = time()
self.update()
- def updateAmount(self, newAmount = 0):
+ def updateAmount(self, newAmount = 0, finished = False):
if newAmount < self.min:
newAmount = self.min
if newAmount > self.max:
- newAmount = self.max
+ newAmount = self.max - 1
if self.amount != newAmount:
self.last_amount_update = time()
self.amount = newAmount
@@ -207,6 +249,8 @@ class progressBar:
percentDone = round(timeElapsed * 100 / self.eta)
except:
percentDone = 0
+ if percentDone >= 100 and not finished:
+ percentDone = 99
if percentDone > 100:
percentDone = 100
ETA = timeElapsed
@@ -241,7 +285,7 @@ class progressBar:
self.updateAmount(self.amount+toInc)
def finished(self):
- self.updateAmount(self.max)
+ self.updateAmount(self.max, finished = True)
sys.stdout.write(self.progBar + '\n')
sys.stdout.flush()
@@ -315,6 +359,14 @@ class XmlReport:
outfn.write(self.doc.serialize(None,1))
outfn.close()
+# if debugging is enabled, allow plugins to raise exceptions
+
+if __cmdLineOpts__.debug:
+ sys.excepthook = doException
+ __raisePlugins__ = 1
+else:
+ __raisePlugins__ = 0
+
def sosreport():
# pylint: disable-msg = R0912
# pylint: disable-msg = R0914
@@ -322,6 +374,13 @@ def sosreport():
"""
This is the top-level function that gathers and processes all sosreport information
"""
+
+ global loadedplugins, dstroot, policy
+
+ config = ConfigParser.ConfigParser()
+ try: config.readfp(open('/etc/sos.conf'))
+ except IOError: pass
+
loadedplugins = []
skippedplugins = []
alloptions = []
@@ -336,8 +395,12 @@ def sosreport():
pluginpath = path + "/sos/plugins"
# Set up common info and create destinations
+
+ dstroot = policy.getDstroot()
+ if not dstroot:
+ print _("Could not create temporary directory.")
+ doExit()
- dstroot = sosFindTmpDir()
cmddir = os.path.join(dstroot, "sos_commands")
logdir = os.path.join(dstroot, "sos_logs")
rptdir = os.path.join(dstroot, "sos_reports")
@@ -346,7 +409,7 @@ def sosreport():
os.mkdir(rptdir, 0755)
# initialize i18n language localization
- gettext.install('sos', '/usr/share/locale', unicode=False)
+ gettext.install('sos', '/usr/share/locale', unicode=False)
# initialize logging
soslog = logging.getLogger('sos')
@@ -354,12 +417,15 @@ def sosreport():
logging.VERBOSE = logging.INFO - 1
logging.VERBOSE2 = logging.INFO - 2
- logging.VERBOSE3 = logging.INFO - 3
+ logging.VERBOSE3 = logging.INFO - 3
logging.addLevelName(logging.VERBOSE, "verbose")
logging.addLevelName(logging.VERBOSE2,"verbose2")
logging.addLevelName(logging.VERBOSE3,"verbose3")
- # FIXME: strip colours if terminal doesn't allow it
+ # if stdin is not a tty, disable colors and don't ask questions
+ if not sys.stdin.isatty():
+ __cmdLineOpts__.nocolors = True
+ __cmdLineOpts__.batch = True
# log to a file
flog = logging.FileHandler(logdir + "/sos.log")
@@ -382,7 +448,7 @@ def sosreport():
# set up dict so everyone can share the following
commons = {'dstroot': dstroot, 'cmddir': cmddir, 'logdir': logdir, 'rptdir': rptdir,
'soslog': soslog, 'policy': policy, 'verbosity' : __cmdLineOpts__.verbosity,
- 'xmlreport' : xmlrep }
+ 'xmlreport' : xmlrep, 'cmdlineopts':__cmdLineOpts__, 'config':config }
# Make policy aware of the commons
policy.setCommons(commons)
@@ -390,12 +456,11 @@ def sosreport():
print
soslog.info ( _("sosreport (version %s)") % __version__)
print
-
+
# generate list of available plugins
plugins = os.listdir(pluginpath)
plugins.sort()
-
- # FIXME: should at least print a warning if the user references a plugin which does not exist
+ plugin_names = []
# validate and load plugins
for plug in plugins:
@@ -403,36 +468,33 @@ def sosreport():
if not plug[-3:] == '.py' or plugbase == "__init__":
continue
try:
- #print "importing plugin: %s" % plugbase
- try:
- if policy.validatePlugin(pluginpath + plug):
- pluginClass = importPlugin("sos.plugins." + plugbase, plugbase)
- else:
- soslog.warning(_("plugin %s does not validate, skipping") % plug)
- skippedplugins.append((plugbase, pluginClass(plugbase, commons)))
- continue
- if plugbase in __cmdLineOpts__.noplugins:
- soslog.log(logging.VERBOSE, _("plugin %s skipped (--skip-plugins)") % plugbase)
- skippedplugins.append((plugbase, pluginClass(plugbase, commons)))
- continue
- if not pluginClass(plugbase, commons).checkenabled() and not plugbase in __cmdLineOpts__.enableplugins and not plugbase in __cmdLineOpts__.onlyplugins:
- soslog.log(logging.VERBOSE, _("plugin %s is inactive (use -e or -o to enable).") % plug)
- skippedplugins.append((plugbase, pluginClass(plugbase, commons)))
- continue
- if not pluginClass(plugbase, commons).defaultenabled() and not plugbase in __cmdLineOpts__.enableplugins and not plugbase in __cmdLineOpts__.onlyplugins:
- soslog.log(logging.VERBOSE, "plugin %s not loaded by default (use -e or -o to enable)." % plug)
- skippedplugins.append((plugbase, pluginClass(plugbase, commons)))
- continue
- if __cmdLineOpts__.onlyplugins and not plugbase in __cmdLineOpts__.onlyplugins:
- soslog.log(logging.VERBOSE, _("plugin %s not specified in --only-plugins list") % plug)
- skippedplugins.append((plugbase, pluginClass(plugbase, commons)))
- continue
- loadedplugins.append((plugbase, pluginClass(plugbase, commons)))
- except:
- soslog.warning(_("plugin %s does not install, skipping") % plug)
- raise
+ if policy.validatePlugin(pluginpath + plug):
+ pluginClass = importPlugin("sos.plugins." + plugbase, plugbase)
+ else:
+ soslog.warning(_("plugin %s does not validate, skipping") % plug)
+ skippedplugins.append((plugbase, pluginClass(plugbase, commons)))
+ continue
+ # plug-in is valid, let's decide whether run it or not
+ plugin_names.append(plugbase)
+ if plugbase in __cmdLineOpts__.noplugins:
+ soslog.log(logging.VERBOSE, _("plugin %s skipped (--skip-plugins)") % plugbase)
+ skippedplugins.append((plugbase, pluginClass(plugbase, commons)))
+ continue
+ if not pluginClass(plugbase, commons).checkenabled() and not plugbase in __cmdLineOpts__.enableplugins and not plugbase in __cmdLineOpts__.onlyplugins:
+ soslog.log(logging.VERBOSE, _("plugin %s is inactive (use -e or -o to enable).") % plug)
+ skippedplugins.append((plugbase, pluginClass(plugbase, commons)))
+ continue
+ if not pluginClass(plugbase, commons).defaultenabled() and not plugbase in __cmdLineOpts__.enableplugins and not plugbase in __cmdLineOpts__.onlyplugins:
+ soslog.log(logging.VERBOSE, "plugin %s not loaded by default (use -e or -o to enable)." % plug)
+ skippedplugins.append((plugbase, pluginClass(plugbase, commons)))
+ continue
+ if __cmdLineOpts__.onlyplugins and not plugbase in __cmdLineOpts__.onlyplugins:
+ soslog.log(logging.VERBOSE, _("plugin %s not specified in --only-plugins list") % plug)
+ skippedplugins.append((plugbase, pluginClass(plugbase, commons)))
+ continue
+ loadedplugins.append((plugbase, pluginClass(plugbase, commons)))
except:
- soslog.warning(_("could not load plugin %s") % plug)
+ soslog.warning(_("plugin %s does not install, skipping") % plug)
if __raisePlugins__:
raise
@@ -444,6 +506,14 @@ def sosreport():
if type(parms["enabled"])==bool:
parms["enabled"] = True
+ # read plugin tunables from configuration file
+ if config.has_section("tunables"):
+ if not __cmdLineOpts__.plugopts:
+ __cmdLineOpts__.plugopts = []
+
+ for opt, val in config.items("tunables"):
+ __cmdLineOpts__.plugopts.append(opt + "=" + val)
+
if __cmdLineOpts__.plugopts:
opts = {}
for opt in __cmdLineOpts__.plugopts:
@@ -453,7 +523,7 @@ def sosreport():
except:
val=True
else:
- if val == "off" or val == "disable" or val == "disabled":
+ if val.lower() in ["off", "disable", "disabled", "false"]:
val = False
else:
# try to convert string "val" to int()
@@ -461,7 +531,11 @@ def sosreport():
except: pass
# split up "general.syslogsize"
- plug, opt = opt.split(".")
+ try:
+ plug, opt = opt.split(".")
+ except:
+ plug = opt
+ opt = True
try: opts[plug]
except KeyError: opts[plug] = []
@@ -470,10 +544,26 @@ def sosreport():
for plugname, plug in loadedplugins:
if opts.has_key(plugname):
for opt,val in opts[plugname]:
- soslog.log(logging.VERBOSE, "setting option %s for plugin %s to %s" % (plugname,opt,val))
- plug.setOption(opt,val)
+ soslog.log(logging.VERBOSE, 'setting option "%s" for plugin (%s) to "%s"' % (plugname,opt,val))
+ if not plug.setOption(opt,val):
+ soslog.error('no such option "%s" for plugin (%s)' % (opt,plugname))
+ doExit(1)
+ del opts[plugname]
+ for plugname in opts.keys():
+ soslog.error('unable to set option for disabled or non-existing plugin (%s)' % (plugname))
+ doExit(1)
del opt,opts,val
+ # error if the user references a plugin which does not exist
+ unk_plugs = [plugname.split(".")[0] for plugname in __cmdLineOpts__.onlyplugins if not plugname.split(".")[0] in plugin_names]
+ unk_plugs += [plugname.split(".")[0] for plugname in __cmdLineOpts__.noplugins if not plugname.split(".")[0] in plugin_names]
+ unk_plugs += [plugname.split(".")[0] for plugname in __cmdLineOpts__.enableplugins if not plugname.split(".")[0] in plugin_names]
+ if len(unk_plugs):
+ for plugname in unk_plugs:
+ soslog.error('a non-existing plugin (%s) was specified in the command line' % (plugname))
+ doExit(1)
+ del unk_plugs
+
for plugname, plug in loadedplugins:
soslog.log(logging.VERBOSE3, _("processing options from plugin: %s") % plugname)
names, parms = plug.getAllOptions()
@@ -487,7 +577,7 @@ def sosreport():
if __cmdLineOpts__.listPlugins:
if not len(loadedplugins) and not len(skippedplugins):
soslog.error(_("no valid plugins found"))
- sys.exit(1)
+ doExit(1)
# FIXME: make -l output more concise
if len(loadedplugins):
@@ -530,26 +620,22 @@ def sosreport():
print _("No plugin options available.")
print
- sys.exit()
+ doExit()
# to go anywhere further than listing the plugins we will need root permissions.
#
if os.getuid() != 0:
print _('sosreport requires root permissions to run.')
- sys.exit(1)
+ doExit(1)
# we don't need to keep in memory plugins we are not going to use
del skippedplugins
if not len(loadedplugins):
soslog.error(_("no valid plugins were enabled"))
- sys.exit(1)
+ doExit(1)
- isUnattended = False
- if len(__cmdLineOpts__.name) > 0 and len(__cmdLineOpts__.ticketnumber) > 0: isUnattended = True
- if not isUnattended:
- try:
- raw_input(_("""This utility will collect some detailed information about the
+ msg = _("""This utility will collect some detailed information about the
hardware and setup of your Red Hat Enterprise Linux system.
The information is collected and an archive is packaged under
/tmp, which you can send to a support representative.
@@ -559,11 +645,14 @@ and it will be considered confidential information.
This process may take a while to complete.
No changes will be made to your system.
-Press ENTER to continue, or CTRL-C to quit.
-"""))
- except KeyboardInterrupt:
- print
- sys.exit(0)
+""")
+ if __cmdLineOpts__.batch:
+ print msg
+ else:
+ msg += _("""Press ENTER to continue, or CTRL-C to quit.\n""")
+ try: raw_input(msg)
+ except: print ; doExit()
+ del msg
# Call the diagnose() method for each plugin
tmpcount = 0
@@ -590,37 +679,32 @@ Press ENTER to continue, or CTRL-C to quit.
fp.close()
print
- try:
- while True:
- if not isUnattended:
+ if not __cmdLineOpts__.batch:
+ try:
+ while True:
yorno = raw_input( _("Are you sure you would like to continue (y/n) ? ") )
- else:
- yorno = _("Y")
-
- if yorno == _("y") or yorno == _("Y"):
- print
- break
- elif yorno == _("n") or yorno == _("N"):
- sys.exit(0)
- del yorno
- except KeyboardInterrupt:
- print
- sys.exit(0)
-
- if isUnattended:
- policy.preWork(__cmdLineOpts__.name, __cmdLineOpts__.ticketnumber)
- else:
- policy.preWork()
-
+ if yorno == _("y") or yorno == _("Y"):
+ print
+ break
+ elif yorno == _("n") or yorno == _("N"):
+ doExit(0)
+ del yorno
+ except KeyboardInterrupt:
+ print
+ doExit(0)
+
+ policy.preWork()
# Call the setup() method for each plugin
for plugname, plug in loadedplugins:
soslog.log(logging.VERBOSE2, "Preloading files and commands to be gathered by plugin %s" % plugname)
try:
- plug.setup()
+ plug.setup()
+ except KeyboardInterrupt:
+ raise
except:
- if __raisePlugins__:
- raise
+ if __raisePlugins__:
+ raise
# Setup the progress bar
if __cmdLineOpts__.progressbar:
@@ -639,15 +723,17 @@ Press ENTER to continue, or CTRL-C to quit.
# Call the collect method for each plugin
plugrunning = Semaphore(2)
for plugname, plug in loadedplugins:
- soslog.log(logging.VERBOSE, "executing plugin %s" % plugname)
+ soslog.log(logging.VERBOSE, "requesting plugin %s" % plugname)
try:
if not __cmdLineOpts__.nomultithread:
plug.copyStuff(threaded = True, semaphore = plugrunning)
else:
- plug.copyStuff()
+ plug.copyStuff()
if __cmdLineOpts__.progressbar:
pbar.incAmount(plug.eta_weight)
pbar.update()
+ except KeyboardInterrupt:
+ raise
except:
if __raisePlugins__:
raise
@@ -755,8 +841,6 @@ Press ENTER to continue, or CTRL-C to quit.
rfd.close()
- # Collect any needed user information (name, etc)
-
# Call the postproc method for each plugin
for plugname, plug in loadedplugins:
try:
@@ -767,14 +851,23 @@ Press ENTER to continue, or CTRL-C to quit.
# package up the results for the support organization
policy.packageResults()
+
# delete gathered files
- os.system("/bin/rm -rf %s" % dstroot)
+ policy.cleanDstroot()
+
+ # let's encrypt the tar-ball
+ #if __cmdLineOpts__.encrypt:
+ # policy.encryptResults()
+
# automated submission will go here
+ if not __cmdLineOpts__.upload:
+ policy.displayResults()
+ else:
+ policy.uploadResults()
# Close all log files and perform any cleanup
logging.shutdown()
-
-
+
if __name__ == '__main__':
try:
sosreport()
diff --git a/src/sosreport.1 b/src/sosreport.1
index cd7d34df..3ae187a8 100644
--- a/src/sosreport.1
+++ b/src/sosreport.1
@@ -44,19 +44,21 @@ Do not display a progress bar (ETA will not be available).
.TP
.B \--no-multithread
Disable multithreaded collection and analysis of the sosreport data.
-.SH MAINTAINERS
+.SH MAINTAINER
.nf
Navid Sheikhol-Eslami <navid@redhat.com>
.fi
-.SH TRANSLATIONS
-.nf
-Eva Schaller <eschalle@redhat.com> [Italian]
-Imed Chihi <ichihi@redhat.com> [Arabic] [French]
-.fi
.SH AUTHORS
.nf
Steve Conklin <sconklin@redhat.com>
John Berninger <jwb@redhat.com>
-Navid Sheikhol-Eslami <navid@redhat.com>
Pierre Amadio <pamadio@redhat.com>
+Adam Stokes <astokes@redhat.com>
+.fi
+.SH THANKS TO
+.nf
+Eva Schaller <eschaller@redhat.com> for providing an Italian translation
+Marco Ceci <mceci@redhat.com> for helping me out with the cluster plugin
+Leonardo Macchia <lmacchia@redhat.com> for being my personal regexp generator
+Imed Chihi <ichihi@redhat.com> for providing Arabic and French translations
.fi