aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xsrc/lib/sos/helpers.py57
-rw-r--r--src/lib/sos/plugins/autofs.py31
-rw-r--r--src/lib/sos/plugins/cluster.py4
-rw-r--r--src/lib/sos/plugins/devicemapper.py16
-rw-r--r--src/lib/sos/plugins/general.py12
-rw-r--r--src/lib/sos/plugins/hardware.py17
-rw-r--r--src/lib/sos/plugins/kernel.py4
-rw-r--r--src/lib/sos/plugins/ldap.py21
-rw-r--r--src/lib/sos/plugins/named.py15
-rw-r--r--src/lib/sos/plugins/pam.py2
-rw-r--r--src/lib/sos/plugins/rpm.py4
-rw-r--r--src/lib/sos/plugintools.py35
-rwxr-xr-xsrc/lib/sos/policyredhat.py57
-rw-r--r--src/sos.spec5
-rwxr-xr-xsrc/sosreport86
15 files changed, 192 insertions, 174 deletions
diff --git a/src/lib/sos/helpers.py b/src/lib/sos/helpers.py
index 61ce8487..77f85b01 100755
--- a/src/lib/sos/helpers.py
+++ b/src/lib/sos/helpers.py
@@ -25,9 +25,29 @@
"""
helper functions used by sosreport and plugins
"""
-import os, popen2, fcntl, select, itertools, sys, commands, logging, signal
+import os, popen2, fcntl, select, sys, commands, signal
from time import time, sleep
-from tempfile import mkdtemp
+
+if sys.version_info[0] <= 2 and sys.version_info[1] <= 2:
+ # it's a RHEL3, activate work-arounds
+ #
+ import sos.rhel3_logging
+ logging = sos.rhel3_logging
+
+ def mkdtemp(suffix = "", prefix = "temp_"):
+ import random
+ while True:
+ tempdir = "/tmp/%s_%d%s" % (prefix, random.randint(1,9999999), suffix)
+ if not os.path.exists(tempdir): break
+ os.mkdir(tempdir)
+ return tempdir
+
+ os.path.sep = "/"
+ os.path.pardir = ".."
+else:
+ # RHEL4+, business as usual
+ import logging
+ from tempfile import mkdtemp
def importPlugin(pluginname, name):
""" Import a plugin to extend capabilities of sosreport
@@ -81,16 +101,16 @@ def sosGetCommandOutput(command, timeout = 300):
if pid:
# we are the parent
os.close(w) # use os.close() to close a file descriptor
- oldr = r
- r = os.fdopen(r) # turn r into a file object
+ r_fd = os.fdopen(r) # turn r into a file object
stime=time()
txt = ""
sts = -1
+ soslog.log(logging.VERBOSE2, 'forked command "%s" with pid %d, timeout is %d' % (command, pid, timeout) )
while True:
# read output from pipe
- ready = select.select([oldr],[],[],1)
- if len(ready[0]):
- txt = txt + r.read()
+ ready = select.select([r], [], [], 1)
+ if r in ready[0]:
+ txt = txt + r_fd.read()
# is child still running ?
try: os.waitpid(pid, os.WNOHANG)
except:
@@ -101,7 +121,8 @@ def sosGetCommandOutput(command, timeout = 300):
# has timeout passed ?
if time() - stime > timeout:
soslog.log(logging.VERBOSE, 'killing hung child with pid %s after %d seconds (command was "%s")' % (pid,timeout,command) )
- os.kill(pid, signal.SIGKILL)
+ try: os.kill(pid, signal.SIGKILL)
+ except: pass
break
if txt[-1:] == '\n': txt = txt[:-1]
return (sts, txt, time()-stime)
@@ -113,6 +134,8 @@ def sosGetCommandOutput(command, timeout = 300):
import resource
maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
+ if not hasattr(resource, "RLIM_INFINITY"):
+ resource.RLIM_INFINITY = -1L
if (maxfd == resource.RLIM_INFINITY):
maxfd = MAXFD
for fd in range(3, maxfd):
@@ -144,23 +167,11 @@ def allEqual(elements):
return False
return True
-
-def commonPrefix(*sequences):
+def commonPrefix(l1, l2, common = []):
''' return a list of common elements at the start of all sequences,
then a list of lists that are the unique tails of each sequence. '''
- # if there are no sequences at all, we're done
- if not sequences:
- return [], []
- # loop in parallel on the sequences
- common = []
- for elements in itertools.izip(*sequences):
- # unless all elements are equal, bail out of the loop
- if not allEqual(elements):
- break
- # got one more common element, append it and keep looping
- common.append(elements[0])
- # return the common prefix and unique tails
- return common, [ sequence[len(common):] for sequence in sequences ]
+ if len(l1) < 1 or len(l2) < 1 or l1[0] != l2[0]: return common, [l1, l2]
+ return commonPrefix(l1[1:], l2[1:], common+[l1[0]])
def sosRelPath(path1, path2, sep=os.path.sep, pardir=os.path.pardir):
''' return a relative path from path1 equivalent to path path2.
diff --git a/src/lib/sos/plugins/autofs.py b/src/lib/sos/plugins/autofs.py
index 5e8be418..16a8d3fb 100644
--- a/src/lib/sos/plugins/autofs.py
+++ b/src/lib/sos/plugins/autofs.py
@@ -25,38 +25,7 @@ class autofs(sos.plugintools.PluginBase):
return True
return False
- def checkdebug(self):
- """
- Probably not needed? I think we can pretty much assume that if daemon.* is
- set in /etc/syslog.conf then debugging is enabled.
- FIXME: remove checkdebug if not needed in future release
- """
- pass
- # Global debugging
- optlist=[]
- opt = self.doRegexFindAll(r"^(DEFAULT_LOGGING|DAEMONOPTIONS)=(.*)", "/etc/sysconfig/autofs")
- for opt1 in opt:
- optlist.append(opt1)[1]
- for dtest in optlist:
- if dtest == "--debug" or dtest == "debug":
- return True
-
- def getdaemondebug(self):
- """ capture daemon debug output
- """
- debugout=self.doRegexFindAll(r"^daemon.*\s+(\/var.*)", "/etc/syslog.conf")
- for i in debugout:
- return i
-
def setup(self):
self.addCopySpec("/etc/auto*")
self.addCopySpec("/etc/sysconfig/autofs")
self.addCopySpec("/etc/rc.d/init.d/autofs")
- self.collectExtOutput("service autofs status")
-
- # if debugging to file is enabled, grab that file too
- daemon_debug_file = self.getdaemondebug()
- if daemon_debug_file:
- self.addCopySpec(daemon_debug_file)
- return
-
diff --git a/src/lib/sos/plugins/cluster.py b/src/lib/sos/plugins/cluster.py
index 280ad3b1..1ef4fe2a 100644
--- a/src/lib/sos/plugins/cluster.py
+++ b/src/lib/sos/plugins/cluster.py
@@ -25,10 +25,6 @@ class cluster(sos.plugintools.PluginBase):
('taskdump', 'trigger 3 sysrq+t dumps every 5 seconds (dangerous)', 'slow', False)]
def checkenabled(self):
- self.files = [ "/etc/yum.conf" ]
- self.packages = [ "yum" ]
-
- def checkenabled(self):
rhelver = self.cInfo["policy"].rhelVersion()
if rhelver == 4:
self.packages = [ "ccs", "cman", "cman-kernel", "magma", "magma-plugins",
diff --git a/src/lib/sos/plugins/devicemapper.py b/src/lib/sos/plugins/devicemapper.py
index c2be8eba..5a1b63c2 100644
--- a/src/lib/sos/plugins/devicemapper.py
+++ b/src/lib/sos/plugins/devicemapper.py
@@ -22,11 +22,6 @@ class devicemapper(sos.plugintools.PluginBase):
optionList = [("lvmdump", 'collect raw metadata from PVs', 'slow', False)]
- def do_lvmdump(self):
- """Collects raw metadata directly from the PVs using dd
- """
- sosGetCommandOutput("lvmdump -d %s" % os.path.join(self.cInfo['dstroot'],"lvmdump"))
-
def setup(self):
self.collectExtOutput("/sbin/dmsetup info -c")
self.collectExtOutput("/sbin/dmsetup table")
@@ -51,11 +46,12 @@ class devicemapper(sos.plugintools.PluginBase):
self.collectExtOutput("/bin/ls -laR /sys/block")
if self.getOption('lvmdump'):
- self.do_lvmdump()
+ sosGetCommandOutput("lvmdump -d %s" % os.path.join(self.cInfo['dstroot'],"lvmdump"))
- for disk in os.listdir("/sys/block"):
- if disk in [ ".", ".." ] or disk.startswith("ram"):
- continue
- self.collectExtOutput("/usr/bin/udevinfo -ap /sys/block/%s" % (disk))
+ if os.path.isdir("/sys/block"):
+ for disk in os.listdir("/sys/block"):
+ if disk in [ ".", ".." ] or disk.startswith("ram"):
+ continue
+ self.collectExtOutput("/usr/bin/udevinfo -ap /sys/block/%s" % (disk))
return
diff --git a/src/lib/sos/plugins/general.py b/src/lib/sos/plugins/general.py
index 6f1f912c..c124c001 100644
--- a/src/lib/sos/plugins/general.py
+++ b/src/lib/sos/plugins/general.py
@@ -12,6 +12,7 @@
## along with this program; if not, write to the Free Software
## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+import os
import sos.plugintools
import glob
@@ -19,7 +20,8 @@ class general(sos.plugintools.PluginBase):
"""basic system information
"""
- optionList = [("syslogsize", "max size (MiB) to collect per syslog file", "", 15)]
+ optionList = [("syslogsize", "max size (MiB) to collect per syslog file", "", 15),
+ ("all_logs", "collect all log files defined in syslog.conf", "", False)]
def setup(self):
self.addCopySpec("/etc/redhat-release")
@@ -37,6 +39,14 @@ class general(sos.plugintools.PluginBase):
self.collectExtOutput("/bin/date", root_symlink = "date")
self.collectExtOutput("/usr/bin/uptime", root_symlink = "uptime")
self.collectExtOutput("/bin/env")
+
+ if self.getOption('all_logs'):
+ logs=self.doRegexFindAll(r"^\S+\s+(\S+)", "/etc/syslog.conf")
+ for i in logs:
+ i = i.lstrip("-")
+ if not os.path.isfile(i): continue
+ self.addCopySpec(i)
+
return
def postproc(self):
diff --git a/src/lib/sos/plugins/hardware.py b/src/lib/sos/plugins/hardware.py
index 22f13e6d..ad4a5537 100644
--- a/src/lib/sos/plugins/hardware.py
+++ b/src/lib/sos/plugins/hardware.py
@@ -36,23 +36,12 @@ class hardware(sos.plugintools.PluginBase):
self.addCopySpec("/proc/dasd")
self.addCopySpec("/proc/s390dbf/tape")
self.collectExtOutput("/usr/share/rhn/up2dateclient/hardware.py")
- self.collectExtOutput("""/bin/echo "lspci:" ; /bin/echo ; /sbin/lspci ; /bin/echo ; /bin/echo "lspci -nvv:" ; /bin/echo ; /sbin/lspci -nvv""", suggest_filename = "lspci", root_symlink = "lspci")
+ self.collectExtOutput("""/bin/echo -e "lspci:\n" ; /sbin/lspci ; /bin/echo -e "\nlspci -nvv:\n" ; /sbin/lspci -nvv ; /bin/echo -e "\nlspci -tv:\n" ; /sbin/lspci -tv""", suggest_filename = "lspci", root_symlink = "lspci")
self.collectExtOutput("/usr/sbin/dmidecode", root_symlink = "dmidecode")
- # FIXME: if arch == i386:
-# self.collectExtOutput("/usr/sbin/x86info -a")
-
- # FIXME: what is this for?
- self.collectExtOutput("/bin/dmesg | /bin/grep -e 'e820.' -e 'agp.'")
-
- # FIXME: what is this for?
- tmpreg = ""
- for hwmodule in commands.getoutput('cat /lib/modules/$(uname -r)/modules.pcimap | cut -d " " -f 1 | grep "[:alpha:]" | sort -u').split("\n"):
- hwmodule = hwmodule.strip()
- if len(hwmodule):
- tmpreg = tmpreg + "|" + hwmodule
- self.collectExtOutput("/bin/dmesg | /bin/egrep '(%s)'" % tmpreg[1:])
+ if self.cInfo["policy"].getArch().endswith("386"):
+ self.collectExtOutput("/usr/sbin/x86info -a")
self.collectExtOutput("/sbin/lsusb")
self.collectExtOutput("/usr/bin/lshal")
diff --git a/src/lib/sos/plugins/kernel.py b/src/lib/sos/plugins/kernel.py
index f2e6def3..9a662fe7 100644
--- a/src/lib/sos/plugins/kernel.py
+++ b/src/lib/sos/plugins/kernel.py
@@ -64,9 +64,7 @@ class kernel(sos.plugintools.PluginBase):
self.addCopySpec("/proc/filesystems")
self.addCopySpec("/proc/ksyms")
self.addCopySpec("/proc/slabinfo")
- # FIXME: kver should have this stuff cached somewhere
- kver = commands.getoutput('/bin/uname -r')
- self.addCopySpec("/lib/modules/%s/modules.dep" % kver)
+ self.addCopySpec("/lib/modules/%s/modules.dep" % self.cInfo["policy"].kernelVersion())
self.addCopySpec("/etc/conf.modules")
self.addCopySpec("/etc/modules.conf")
self.addCopySpec("/etc/modprobe.conf")
diff --git a/src/lib/sos/plugins/ldap.py b/src/lib/sos/plugins/ldap.py
index 47ac0612..e4779178 100644
--- a/src/lib/sos/plugins/ldap.py
+++ b/src/lib/sos/plugins/ldap.py
@@ -18,6 +18,11 @@ import os
class ldap(sos.plugintools.PluginBase):
"""LDAP related information
"""
+ def checkenabled(self):
+ self.packages = [ "openldap" ]
+ self.files = [ "/etc/openldap/ldap.conf" ]
+ return sos.plugintools.PluginBase.checkenabled(self)
+
def get_ldap_opts(self):
# capture /etc/openldap/ldap.conf options in dict
# FIXME: possibly not hardcode these options in?
@@ -30,30 +35,16 @@ class ldap(sos.plugintools.PluginBase):
results[x[0]]=x[1].rstrip("\n")
return results
- def get_slapd_debug(self):
- """ Capture debugging information based on an existing log level
- """
- loglevel=self.doRegexFindAll(r"^local4.*\s+(\/var.*)", "/etc/syslog.conf")
- for i in loglevel:
- return i
-
def diagnose(self):
# Validate ldap client options
ldapopts=self.get_ldap_opts()
- if ldapopts.has_key("TLS_CACERTDIR"):
- try:
- os.stat(ldapopts["TLS_CACERTDIR"])
- except:
+ if ldapopts.has_key("TLS_CACERTDIR") and os.path.exists(ldapopts["TLS_CACERTDIR"]):
self.addDiagnose("%s does not exist and can cause connection issues involving TLS" % ldapopts["TLS_CACERTDIR"])
def setup(self):
self.addCopySpec("/etc/ldap.conf")
self.addCopySpec("/etc/openldap")
- slapd_debug_file = self.get_slapd_debug()
- if slapd_debug_file:
- self.addCopySpec(slapd_debug_file)
-
def postproc(self):
self.doRegexSub("/etc/ldap.conf", r"(\s*bindpw\s*)\S+", r"\1***")
return
diff --git a/src/lib/sos/plugins/named.py b/src/lib/sos/plugins/named.py
index f4d24e19..bb0d079e 100644
--- a/src/lib/sos/plugins/named.py
+++ b/src/lib/sos/plugins/named.py
@@ -21,20 +21,13 @@ class named(sos.plugintools.PluginBase):
"""
def checkenabled(self):
self.files = [ "/etc/named.conf", "/etc/sysconfig/named" ]
- self.packages = [ "bind" ]
+ self.packages = [ "bind", "bind-chroot" ]
return sos.plugintools.PluginBase.checkenabled(self)
def setup(self):
- dnsdir = ""
self.addCopySpec("/etc/named.boot")
self.addCopySpec("/etc/named.conf")
self.addCopySpec("/etc/sysconfig/named")
- # FIXME: use internal fileGrep() instead
- if os.access("/etc/named.conf", os.R_OK):
- dnsdir = commands.getoutput("/bin/grep -i directory /etc/named.conf | /bin/gawk '{print $2}' | /bin/sed 's/\\\"//g' | /bin/sed 's/\;//g'")
- if os.access("/etc/named.boot", os.R_OK):
- dnsdir = commands.getoutput("/bin/grep -i directory /etc/named.boot | /bin/gawk '{print $2}' | /bin/sed 's/\\\"//g' | /bin/sed 's/\;//g'")
- if '' != dnsdir.strip():
- self.addCopySpec(dnsdir)
- self.addForbiddenPath('/var/named/chroot/proc')
- self.addForbiddenPath('/var/named/chroot/dev')
+ self.addCopySpec("/var/named")
+ self.addForbiddenPath('/var/named/chroot/proc')
+ self.addForbiddenPath('/var/named/chroot/dev')
diff --git a/src/lib/sos/plugins/pam.py b/src/lib/sos/plugins/pam.py
index 8164bba3..1a50811b 100644
--- a/src/lib/sos/plugins/pam.py
+++ b/src/lib/sos/plugins/pam.py
@@ -20,6 +20,6 @@ class pam(sos.plugintools.PluginBase):
def setup(self):
self.addCopySpec("/etc/pam.d")
self.addCopySpec("/etc/security")
- self.collectExtOutput("/bin/ls -laF /lib/security/pam_*so")
+ self.collectExtOutput("/bin/ls -laF /lib/security")
return
diff --git a/src/lib/sos/plugins/rpm.py b/src/lib/sos/plugins/rpm.py
index 279dde4c..f1c09e33 100644
--- a/src/lib/sos/plugins/rpm.py
+++ b/src/lib/sos/plugins/rpm.py
@@ -27,7 +27,7 @@ class rpm(sos.plugintools.PluginBase):
self.collectExtOutput("/bin/rpm -qa --qf \"%{NAME}-%{VERSION}-%{RELEASE}-%{ARCH}\n\"", root_symlink = "installed-rpms")
if self.getOption("rpmva"):
- self.eta_weight += 800 # this plugins takes 200x longer (for ETA)
- self.collectExtOutput("/bin/rpm -Va", root_symlink = "rpm-Va")
+ self.eta_weight += 1500 # this plugins takes 200x longer (for ETA)
+ self.collectExtOutput("/bin/rpm -Va", root_symlink = "rpm-Va", timeout = 3600)
return
diff --git a/src/lib/sos/plugintools.py b/src/lib/sos/plugintools.py
index 303e4fc5..2501c450 100644
--- a/src/lib/sos/plugintools.py
+++ b/src/lib/sos/plugintools.py
@@ -30,11 +30,25 @@ This is the base class for sosreport plugins
"""
from sos.helpers import *
from threading import Thread, activeCount
-import os, os.path, sys, string, itertools, glob, re, traceback
-import logging, shutil
+import os, os.path, sys, string, glob, re, traceback
+import shutil
from stat import *
from time import time
+# RHEL3 doesn't have a logging module
+try:
+ import logging
+except ImportError:
+ import sos.rhel3_logging
+ logging = sos.rhel3_logging
+
+# RHEL3 doesn't have format_exc
+if sys.version_info[0] <= 2 and sys.version_info[1] <= 2:
+ def format_exc():
+ return "ciao"
+
+ traceback.format_exc = format_exc
+
class PluginBase:
"""
Base class for plugins
@@ -177,6 +191,7 @@ class PluginBase:
pass
else:
self.doCopyFileOrDir(srcpath+'/'+afile)
+ return
# if we get here, it's definitely a regular file (not a symlink or dir)
@@ -291,11 +306,11 @@ class PluginBase:
status, shout, runtime = sosGetCommandOutput(prog)
return status
- def collectExtOutput(self, exe, suggest_filename = None, root_symlink = None):
+ def collectExtOutput(self, exe, suggest_filename = None, root_symlink = None, timeout = 300):
"""
Run a program and collect the output
"""
- self.collectProgs.append( (exe,suggest_filename,root_symlink) )
+ self.collectProgs.append( (exe, suggest_filename, root_symlink, timeout) )
def fileGrep(self, regexp, fname):
results = []
@@ -331,14 +346,13 @@ class PluginBase:
return outfn
- def collectOutputNow(self, exe, suggest_filename = None, root_symlink = False):
+ def collectOutputNow(self, exe, suggest_filename = None, root_symlink = False, timeout = 300):
""" Execute a command and save the output to a file for inclusion in
the report
"""
- # FIXME: we should have a timeout or we may end waiting forever
# pylint: disable-msg = W0612
- status, shout, runtime = sosGetCommandOutput(exe)
+ status, shout, runtime = sosGetCommandOutput(exe, timeout = timeout)
if suggest_filename:
outfn = self.makeCommandFilename(suggest_filename)
@@ -356,7 +370,8 @@ class PluginBase:
if root_symlink:
curdir = os.getcwd()
os.chdir(self.cInfo['dstroot'])
- os.symlink(outfn[len(self.cInfo['dstroot'])+1:], root_symlink.strip("/."))
+ try: os.symlink(outfn[len(self.cInfo['dstroot'])+1:], root_symlink.strip("/."))
+ except: pass
os.chdir(curdir)
outfn_strip = outfn[len(self.cInfo['cmddir'])+1:]
@@ -469,10 +484,10 @@ class PluginBase:
except Exception, e:
self.soslog.log(logging.VERBOSE2, "error copying from pathspec %s (%s), traceback follows:" % (path,e))
self.soslog.log(logging.VERBOSE2, traceback.format_exc())
- for (prog,suggest_filename,root_symlink) in self.collectProgs:
+ for (prog, suggest_filename, root_symlink, timeout) in self.collectProgs:
self.soslog.debug("collecting output of '%s'" % prog)
try:
- self.collectOutputNow(prog, suggest_filename, root_symlink)
+ self.collectOutputNow(prog, suggest_filename, root_symlink, timeout)
except SystemExit:
if semaphore: semaphore.release()
if threaded: return SystemExit
diff --git a/src/lib/sos/policyredhat.py b/src/lib/sos/policyredhat.py
index 38ded430..2f65dd39 100755
--- a/src/lib/sos/policyredhat.py
+++ b/src/lib/sos/policyredhat.py
@@ -61,7 +61,10 @@ def memoized(function):
class SosPolicy:
"This class implements various policies for sos"
def __init__(self):
- self.report_file = None
+ self.report_file = ""
+ self.report_md5 = ""
+ self.reportName = ""
+ self.ticketNumber = ""
return
def setCommons(self, commons):
@@ -177,6 +180,9 @@ class SosPolicy:
else:
return False
+ def getArch(self):
+ return commands.getoutput("/bin/uname -m").strip()
+
def pkgNVRA(self, pkg):
fields = pkg.split("-")
version, release, arch = fields[-3:]
@@ -200,22 +206,33 @@ class SosPolicy:
localname = self.rhnUsername()
if len(localname) == 0: localname = self.hostName()
- try:
- self.reportName = raw_input(_("Please enter your first initial and last name [%s]: ") % localname)
- self.reportName = re.sub(r"[^a-zA-Z.0-9]", "", self.reportName)
- if len(self.reportName) == 0:
- self.reportName = localname
+ if not self.cInfo['cmdlineopts'].batch:
+ try:
+ self.reportName = raw_input(_("Please enter your first initial and last name [%s]: ") % localname)
+ self.reportName = re.sub(r"[^a-zA-Z.0-9]", "", self.reportName)
- self.ticketNumber = raw_input(_("Please enter the case number that you are generating this report for: "))
- self.ticketNumber = re.sub(r"[^0-9]", "", self.ticketNumber)
- print
- except:
- print
- sys.exit(0)
+ self.ticketNumber = raw_input(_("Please enter the case number that you are generating this report for: "))
+ self.ticketNumber = re.sub(r"[^0-9]", "", self.ticketNumber)
+ print
+ except:
+ print
+ sys.exit(0)
+
+ if len(self.reportName) == 0:
+ self.reportName = localname
+
+ return
+
+ def renameResults(self, newName):
+ newName = os.path.join(gettempdir(), newName)
+ if len(self.report_file) and os.path.isfile(self.report_file):
+ try: os.rename(self.report_file, newName)
+ except: return False
+ self.report_file = newName
def packageResults(self):
- self.report_file = os.path.join(gettempdir(), "sosreport-%s-%s.tar.bz2" % (self.reportName,time.strftime("%Y%m%d%H%M%S")))
+ self.renameResults("sosreport-%s-%s.tar.bz2" % (self.reportName, time.strftime("%Y%m%d%H%M%S")))
tarcmd = "/bin/tar -jcf %s %s" % (self.report_file, os.path.basename(self.cInfo['dstroot']))
@@ -224,7 +241,7 @@ class SosPolicy:
curwd = os.getcwd()
os.chdir(os.path.dirname(self.cInfo['dstroot']))
oldmask = os.umask(077)
- status, shout, runtime = sosGetCommandOutput(tarcmd)
+ status, shout = commands.getstatusoutput(tarcmd)
os.umask(oldmask)
os.chdir(curwd)
@@ -258,19 +275,21 @@ class SosPolicy:
# calculate md5
fp = open(self.report_file, "r")
- md5out = md5.new(fp.read()).hexdigest()
+ self.report_md5 = md5.new(fp.read()).hexdigest()
fp.close()
- # store md5 to a file
+ self.renameResults("sosreport-%s-%s-%s.tar.bz2" % (self.reportName, time.strftime("%Y%m%d%H%M%S"), self.report_md5[-4:]))
+
+ # store md5 into file
fp = open(self.report_file + ".md5", "w")
- fp.write(md5out + "\n")
+ fp.write(self.report_md5 + "\n")
fp.close()
print
print _("Your sosreport has been generated and saved in:\n %s") % self.report_file
print
- if md5out:
- print _("The md5sum is: ") + md5out
+ if len(self.report_md5):
+ print _("The md5sum is: ") + self.report_md5
print
print _("Please send this file to your support representative.")
print
diff --git a/src/sos.spec b/src/sos.spec
index 973be121..5a5e7212 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 10pre1
+%define version 1.8
+%define release 0pre0
%define _localedir %_datadir/locale
@@ -23,6 +23,7 @@ BuildArch: noarch
Url: http://sos.108.redhat.com/
BuildRequires: python-devel
Requires: libxml2-python
+Provides: sysreport = 1.3.15-8
Obsoletes: sysreport
%description
diff --git a/src/sosreport b/src/sosreport
index 88e50a97..d8b631ae 100755
--- a/src/sosreport
+++ b/src/sosreport
@@ -33,14 +33,20 @@ 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
@@ -73,7 +79,7 @@ def doExitCode():
doExit(1)
if ( ( activeCount() > 1 ) and ( __breakHits__ > 1 ) ):
- print "Multiple SIGTERMs, multiple threads, attempting to signal threads to die immediately"
+ print "Multiple SIGTERMs, multiple threads, attempting to signal threads to die immediately."
## FIXME: Add thread-kill code (see FIXME below)
return
elif ( ( activeCount() > 1 ) and ( __breakHits__ > 2 ) ):
@@ -83,7 +89,6 @@ def doExitCode():
print "Multiple SIGTERMs, single thread, exiting without cleaning up."
doExit(3)
- # FIXME: Add code here to clean up /tmp
doExit("Abnormal exit")
def doExit(error=0):
@@ -163,6 +168,12 @@ __cmdParser__.add_option("-u", "--upload", action="store_true", \
__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")
@@ -175,9 +186,21 @@ __cmdParser__.add_option("--no-progressbar", action="store_false", \
__cmdParser__.add_option("--no-multithread", action="store_true", \
dest="nomultithread", \
help="disable multi-threaded gathering mode (slower)", default=False)
+
+if sys.argv[0].endswith("sysreport"):
+ 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")
+ os.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",
@@ -200,11 +223,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
@@ -219,6 +242,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
@@ -253,7 +278,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()
@@ -386,7 +411,10 @@ def sosreport():
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")
@@ -409,7 +437,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__ }
# Make policy aware of the commons
policy.setCommons(commons)
@@ -588,8 +616,7 @@ def sosreport():
soslog.error(_("no valid plugins were enabled"))
doExit(1)
- 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.
@@ -600,10 +627,13 @@ 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:
- print
- doExit()
+""")
+ if __cmdLineOpts__.batch:
+ print msg
+ else:
+ try: raw_input(msg)
+ except: print ; doExit()
+ del msg
# Call the diagnose() method for each plugin
tmpcount = 0
@@ -630,18 +660,19 @@ Press ENTER to continue, or CTRL-C to quit.
fp.close()
print
- try:
- while True:
- yorno = raw_input( _("Are you sure you would like to continue (y/n) ? ") )
- if yorno == _("y") or yorno == _("Y"):
- print
- break
- elif yorno == _("n") or yorno == _("N"):
- doExit(0)
- del yorno
- except KeyboardInterrupt:
- print
- doExit(0)
+ if not __cmdLineOpts__.batch:
+ try:
+ while True:
+ yorno = raw_input( _("Are you sure you would like to continue (y/n) ? ") )
+ 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()
@@ -818,7 +849,6 @@ Press ENTER to continue, or CTRL-C to quit.
# Close all log files and perform any cleanup
logging.shutdown()
-
if __name__ == '__main__':
try:
sosreport()