diff options
39 files changed, 149 insertions, 139 deletions
diff --git a/src/lib/sos/helpers.py b/src/lib/sos/helpers.py index 8ba503c1..09bb356f 100755 --- a/src/lib/sos/helpers.py +++ b/src/lib/sos/helpers.py @@ -25,7 +25,7 @@ """ helper functions used by sosreport and plugins """ -import os, popen2, fcntl, select, itertools, sys +import os, popen2, fcntl, select, itertools, sys, commands from time import time from tempfile import mkdtemp @@ -62,36 +62,9 @@ def sosGetCommandOutput(command): Adapted from Python Cookbook - O'Reilly """ stime = time() - child = popen2.Popen3(command, 1) # Capture stdout and stderr from command - child.tochild.close() # don't need to write to child's stdin - outfile = child.fromchild - outfd = outfile.fileno() - errfile = child.childerr - errfd = errfile.fileno() - makeNonBlocking(outfd) # Don't deadlock! Make fd's nonblocking. - makeNonBlocking(errfd) - outdata, errdata = [], [] - outeof = erreof = False - while True: - to_check = [outfd]*(not outeof) + [errfd]*(not erreof) - ready = select.select(to_check, [], []) # Wait for input - if outfd in ready[0]: - outchunk = outfile.read() - if outchunk == '': - outeof = True - else: - outdata.append(outchunk) - if errfd in ready[0]: - errchunk = errfile.read() - if errchunk == '': - erreof = True - else: - errdata.append(errchunk) - if outeof and erreof: - break - select.select([], [], [], .1) # Allow a little time for buffers to fill - err = child.wait() - return (err, ''.join(outdata), ''.join(errdata), time()-stime) + errdata = '' + status,outdata=commands.getstatusoutput(command) + return (status, ''.join(outdata), time()-stime) # this needs to be made clean and moved to the plugin tools, so diff --git a/src/lib/sos/plugins/amd.py b/src/lib/sos/plugins/amd.py index b87e83f7..1b1375cc 100644 --- a/src/lib/sos/plugins/amd.py +++ b/src/lib/sos/plugins/amd.py @@ -17,7 +17,7 @@ import sos.plugintools class amd(sos.plugintools.PluginBase): - """This plugin gathers Amd automounter information + """Amd automounter information """ def setup(self): self.addCopySpec("/etc/amd.*") diff --git a/src/lib/sos/plugins/apache.py b/src/lib/sos/plugins/apache.py index 78fb725d..c5250fd9 100644 --- a/src/lib/sos/plugins/apache.py +++ b/src/lib/sos/plugins/apache.py @@ -16,7 +16,7 @@ import sos.plugintools from threading import Thread class apache(sos.plugintools.PluginBase): - """This plugin gathers Apache related information + """Apache related information """ def setup(self): self.addCopySpec("/etc/httpd/conf/httpd.conf") diff --git a/src/lib/sos/plugins/bootloader.py b/src/lib/sos/plugins/bootloader.py index f171917f..a820069e 100644 --- a/src/lib/sos/plugins/bootloader.py +++ b/src/lib/sos/plugins/bootloader.py @@ -15,7 +15,7 @@ import sos.plugintools class bootloader(sos.plugintools.PluginBase): - """This plugin gathers bootloader information + """Bootloader information """ def setup(self): self.addCopySpec("/etc/lilo.conf") diff --git a/src/lib/sos/plugins/cluster.py b/src/lib/sos/plugins/cluster.py index bfd5184d..1cead720 100644 --- a/src/lib/sos/plugins/cluster.py +++ b/src/lib/sos/plugins/cluster.py @@ -15,7 +15,7 @@ import sos.plugintools class cluster(sos.plugintools.PluginBase): - """This plugin gathers cluster related information + """cluster related information """ def setup(self): self.collectExtOutput("/sbin/fdisk -l") diff --git a/src/lib/sos/plugins/devicemapper.py b/src/lib/sos/plugins/devicemapper.py index 9627b823..e517aa3d 100644 --- a/src/lib/sos/plugins/devicemapper.py +++ b/src/lib/sos/plugins/devicemapper.py @@ -15,7 +15,7 @@ import sos.plugintools class devicemapper(sos.plugintools.PluginBase): - """This plugin gathers device-mapper related information (dm, lvm, multipath) + """device-mapper related information (dm, lvm, multipath) """ def setup(self): self.collectExtOutput("/sbin/dmsetup info -c") diff --git a/src/lib/sos/plugins/filesys.py b/src/lib/sos/plugins/filesys.py index c7f7dee0..8dc98886 100644 --- a/src/lib/sos/plugins/filesys.py +++ b/src/lib/sos/plugins/filesys.py @@ -16,11 +16,12 @@ import sos.plugintools import commands class filesys(sos.plugintools.PluginBase): - """This plugin gathers infomraiton on filesystems + """information on filesystems """ def setup(self): self.addCopySpec("/proc/filesystems") self.addCopySpec("/etc/fstab") + self.addCopySpec("/proc/self/mounts") self.addCopySpec("/proc/mounts") self.addCopySpec("/proc/mdstat") self.addCopySpec("/etc/raidtab") diff --git a/src/lib/sos/plugins/ftp.py b/src/lib/sos/plugins/ftp.py index 54a50669..026954c0 100644 --- a/src/lib/sos/plugins/ftp.py +++ b/src/lib/sos/plugins/ftp.py @@ -15,7 +15,7 @@ import sos.plugintools class ftp(sos.plugintools.PluginBase): - """This plugin gathers FTP server related information + """FTP server related information """ def setup(self): self.addCopySpec("/etc/ftp*") diff --git a/src/lib/sos/plugins/general.py b/src/lib/sos/plugins/general.py index c9d23bcf..06f55228 100644 --- a/src/lib/sos/plugins/general.py +++ b/src/lib/sos/plugins/general.py @@ -13,18 +13,24 @@ ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. import sos.plugintools +import glob class general(sos.plugintools.PluginBase): - """This plugin gathers very basic system information + """very basic system information """ + + optionList = [("syslogsize", "maximum size (in MiB) of logs to collect per syslog file", "", 15)] + def setup(self): self.addCopySpec("/etc/redhat-release") self.addCopySpec("/etc/sysconfig") self.addCopySpec("/proc/stat") self.addCopySpec("/var/log/dmesg") self.addCopySpec("/var/log/messages") - self.addCopySpec("/var/log/sa") + self.addCopySpecLimit("/var/log/messages.*", sizelimit = self.isOptionEnabled("syslogsize")) self.addCopySpec("/var/log/secure") + self.addCopySpecLimit("/var/log/secure.*", sizelimit = self.isOptionEnabled("syslogsize")) + self.addCopySpec("/var/log/sa") self.addCopySpec("/var/log/up2date") self.addCopySpec("/etc/exports") self.collectExtOutput("/bin/hostname", root_symlink = "hostname") diff --git a/src/lib/sos/plugins/hardware.py b/src/lib/sos/plugins/hardware.py index f5e91d43..f8eeda88 100644 --- a/src/lib/sos/plugins/hardware.py +++ b/src/lib/sos/plugins/hardware.py @@ -16,7 +16,7 @@ import sos.plugintools import commands class hardware(sos.plugintools.PluginBase): - """This plugin gathers hardware related information + """hardware related information """ def setup(self): self.addCopySpec("/proc/partitions") @@ -36,16 +36,19 @@ 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 -n" ; /bin/echo ; /sbin/lspci -nv ; /bin/echo ; /bin/echo "lspci -nvv" ; /bin/echo ; /sbin/lspci -nvv""", suggest_filename = "lspci", root_symlink = "lspci") + self.collectExtOutput("""/bin/echo "lspci" ; /bin/echo ; /sbin/lspci ; /bin/echo ; /bin/echo ; /bin/echo "lspci -nvv" ; /bin/echo ; /sbin/lspci -nvv""", suggest_filename = "lspci", root_symlink = "lspci") + + # 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:]) - + self.collectExtOutput("/sbin/lsusb") self.collectExtOutput("/usr/bin/lshal") return diff --git a/src/lib/sos/plugins/initrd.py b/src/lib/sos/plugins/initrd.py index 00362fbf..83356548 100644 --- a/src/lib/sos/plugins/initrd.py +++ b/src/lib/sos/plugins/initrd.py @@ -16,7 +16,7 @@ import sos.plugintools import glob class initrd(sos.plugintools.PluginBase): - """This plugin gathers initrd related information + """initrd related information """ def setup(self): for initrd in glob.glob('/boot/initrd-*.img'): diff --git a/src/lib/sos/plugins/kernel.py b/src/lib/sos/plugins/kernel.py index 843a590e..f5b0e65d 100644 --- a/src/lib/sos/plugins/kernel.py +++ b/src/lib/sos/plugins/kernel.py @@ -16,7 +16,7 @@ import sos.plugintools import commands, os, re class kernel(sos.plugintools.PluginBase): - """This plugin gathers kernel related information + """kernel related information """ optionList = [("modinfo", 'Gathers module information on all modules', 'fast', 1), ('sysrq', 'Trigger SysRq dumps', 'fast', 1)] @@ -50,10 +50,12 @@ class kernel(sos.plugintools.PluginBase): self.collectExtOutput("/bin/uname -a", root_symlink = "uname") self.moduleFile = self.collectOutputNow("/sbin/lsmod", root_symlink = "lsmod") if self.isOptionEnabled('modinfo'): + runcmd = "" for kmod in commands.getoutput('/sbin/lsmod | /bin/cut -f1 -d" " 2>/dev/null | /bin/grep -v Module 2>/dev/null').split('\n'): if '' != kmod.strip(): - runcmd = "/sbin/modinfo %s" % (kmod,) - self.collectExtOutput(runcmd) + runcmd = runcmd + " " + kmod + if len(runcmd): + self.collectExtOutput("/sbin/modinfo " + runcmd) self.collectExtOutput("/sbin/ksyms") self.addCopySpec("/proc/filesystems") self.addCopySpec("/proc/ksyms") @@ -80,8 +82,7 @@ class kernel(sos.plugintools.PluginBase): commands.getoutput("/bin/echo %s > /proc/sys/kernel/sysrq" % (sysrq_state,)) # No need to grab syslog here if we can't trigger sysrq, so keep this # inside the if - self.addCopySpec("/var/log/messages*") - + self.addCopySpec("/var/log/messages") return diff --git a/src/lib/sos/plugins/ldap.py b/src/lib/sos/plugins/ldap.py index 84ac2a20..318a3ba9 100644 --- a/src/lib/sos/plugins/ldap.py +++ b/src/lib/sos/plugins/ldap.py @@ -15,7 +15,7 @@ import sos.plugintools class ldap(sos.plugintools.PluginBase): - """This plugin gathers LDAP related information + """LDAP related information """ def setup(self): self.addCopySpec("/etc/ldap.conf") diff --git a/src/lib/sos/plugins/libraries.py b/src/lib/sos/plugins/libraries.py index 1ce7b590..70b63dba 100644 --- a/src/lib/sos/plugins/libraries.py +++ b/src/lib/sos/plugins/libraries.py @@ -15,7 +15,7 @@ import sos.plugintools class libraries(sos.plugintools.PluginBase): - """This plugin gathers information on shared libraries + """information on shared libraries """ def setup(self): self.addCopySpec("/etc/ld.so.conf") diff --git a/src/lib/sos/plugins/mail.py b/src/lib/sos/plugins/mail.py index 0f38acf2..0d4dda29 100644 --- a/src/lib/sos/plugins/mail.py +++ b/src/lib/sos/plugins/mail.py @@ -15,7 +15,7 @@ import sos.plugintools class mail(sos.plugintools.PluginBase): - """This plugin gathers mail server related information + """mail server related information """ def setup(self): self.addCopySpec("/etc/mail") diff --git a/src/lib/sos/plugins/memory.py b/src/lib/sos/plugins/memory.py index 43539b77..7fbe39c3 100644 --- a/src/lib/sos/plugins/memory.py +++ b/src/lib/sos/plugins/memory.py @@ -15,7 +15,7 @@ import sos.plugintools class memory(sos.plugintools.PluginBase): - """This plugin gathers memory usage information + """memory usage information """ def setup(self): self.addCopySpec("/proc/pci") diff --git a/src/lib/sos/plugins/named.py b/src/lib/sos/plugins/named.py index 8de3937b..68d56ca0 100644 --- a/src/lib/sos/plugins/named.py +++ b/src/lib/sos/plugins/named.py @@ -17,7 +17,7 @@ import commands import os class named(sos.plugintools.PluginBase): - """This plugin gathers named related information + """named related information """ def setup(self): dnsdir = "" diff --git a/src/lib/sos/plugins/networking.py b/src/lib/sos/plugins/networking.py index 997026ee..54723663 100644 --- a/src/lib/sos/plugins/networking.py +++ b/src/lib/sos/plugins/networking.py @@ -16,7 +16,7 @@ import sos.plugintools import os,re,commands class networking(sos.plugintools.PluginBase): - """This plugin gathers network related information + """network related information """ optionList = [("traceroute", "collects a traceroute to rhn.redhat.com", "slow", 0)] diff --git a/src/lib/sos/plugins/nfsserver.py b/src/lib/sos/plugins/nfsserver.py index efdb832b..6c894177 100644 --- a/src/lib/sos/plugins/nfsserver.py +++ b/src/lib/sos/plugins/nfsserver.py @@ -17,7 +17,7 @@ import sos.plugintools class nfsserver(sos.plugintools.PluginBase): - """This plugin gathers NFS server-related information + """NFS server-related information """ def setup(self): self.addCopySpec("/etc/exports") diff --git a/src/lib/sos/plugins/pam.py b/src/lib/sos/plugins/pam.py index ee95b5a8..8164bba3 100644 --- a/src/lib/sos/plugins/pam.py +++ b/src/lib/sos/plugins/pam.py @@ -15,7 +15,7 @@ import sos.plugintools class pam(sos.plugintools.PluginBase): - """This plugin gathers PAM related information + """PAM related information """ def setup(self): self.addCopySpec("/etc/pam.d") diff --git a/src/lib/sos/plugins/printing.py b/src/lib/sos/plugins/printing.py index 16d2e489..76a476eb 100644 --- a/src/lib/sos/plugins/printing.py +++ b/src/lib/sos/plugins/printing.py @@ -15,7 +15,7 @@ import sos.plugintools class printing(sos.plugintools.PluginBase): - """This plugin gathers printing related information (cups) + """printing related information (cups) """ def setup(self): self.addCopySpec("/etc/cups/*.conf") diff --git a/src/lib/sos/plugins/process.py b/src/lib/sos/plugins/process.py index 552049fd..7ed13a5e 100644 --- a/src/lib/sos/plugins/process.py +++ b/src/lib/sos/plugins/process.py @@ -15,7 +15,7 @@ import sos.plugintools class process(sos.plugintools.PluginBase): - """This plugin gathers process information + """process information """ def setup(self): self.collectExtOutput("/bin/ps auxww", root_symlink = "ps") diff --git a/src/lib/sos/plugins/radius.py b/src/lib/sos/plugins/radius.py index 3104d7b3..7ab53810 100644 --- a/src/lib/sos/plugins/radius.py +++ b/src/lib/sos/plugins/radius.py @@ -17,7 +17,7 @@ import sos.plugintools class radius(sos.plugintools.PluginBase): - """This plugin gathers radius related information + """radius related information """ def setup(self): self.addCopySpec("/etc/raddb") diff --git a/src/lib/sos/plugins/rhn.py b/src/lib/sos/plugins/rhn.py index ff3fc751..049e51bc 100644 --- a/src/lib/sos/plugins/rhn.py +++ b/src/lib/sos/plugins/rhn.py @@ -15,7 +15,7 @@ from sos.plugintools import PluginBase class rhn(PluginBase): - """This plugin gathers RHN server related information + """RHN server related information """ def checkenabled(self): # XXX check for the presence of requisite packages @@ -48,6 +48,9 @@ class rhn(PluginBase): self.addCopySpec("/home/nocpulse/var/*.log*") self.addCopySpec("/home/nocpulse/var/commands/*.log*") + satellite = self.cInfo["policy"].pkgByName("rhns-satellite-tools") + proxy = self.cInfo["policy"].pkgByName("rhns-proxy-tools") + # # Now, go for product-specific data # diff --git a/src/lib/sos/plugins/rpm.py b/src/lib/sos/plugins/rpm.py index 169d675e..b6fdb699 100644 --- a/src/lib/sos/plugins/rpm.py +++ b/src/lib/sos/plugins/rpm.py @@ -15,7 +15,7 @@ import sos.plugintools class rpm(sos.plugintools.PluginBase): - """This plugin gathers RPM information + """RPM information """ optionList = [("rpmq", "Queries for package information via rpm -q", "fast", 1), ("rpmva", "Runs a verify on all packages", "slow", 1)] @@ -27,6 +27,7 @@ class rpm(sos.plugintools.PluginBase): self.collectExtOutput("/bin/rpm -qa --qf \"%{NAME}-%{VERSION}-%{RELEASE}-%{ARCH}\n\"", root_symlink = "installed-rpms") if self.isOptionEnabled("rpmva"): + self.eta_weight += 800 # this plugins takes 200x longer (for ETA) self.collectExtOutput("/bin/rpm -Va", root_symlink = "rpm-Va") return diff --git a/src/lib/sos/plugins/samba.py b/src/lib/sos/plugins/samba.py index 084627bd..ec65370e 100644 --- a/src/lib/sos/plugins/samba.py +++ b/src/lib/sos/plugins/samba.py @@ -15,7 +15,7 @@ import sos.plugintools class samba(sos.plugintools.PluginBase): - """This plugin gathers Samba related information + """Samba related information """ def setup(self): self.addCopySpec("/etc/samba") diff --git a/src/lib/sos/plugins/selinux.py b/src/lib/sos/plugins/selinux.py index 925c2ad7..897c3991 100644 --- a/src/lib/sos/plugins/selinux.py +++ b/src/lib/sos/plugins/selinux.py @@ -16,7 +16,7 @@ import sos.plugintools import commands class selinux(sos.plugintools.PluginBase): - """This plugin gathers selinux related information + """selinux related information """ def setup(self): self.addCopySpec("/etc/selinux/*") diff --git a/src/lib/sos/plugins/sendmail.py b/src/lib/sos/plugins/sendmail.py index 16ac912d..d95b5d7b 100644 --- a/src/lib/sos/plugins/sendmail.py +++ b/src/lib/sos/plugins/sendmail.py @@ -17,7 +17,7 @@ import sos.plugintools class sendmail(sos.plugintools.PluginBase): - """This plugin gathers sendmail information + """sendmail information """ def setup(self): self.addCopySpec("/etc/mail/*") diff --git a/src/lib/sos/plugins/squid.py b/src/lib/sos/plugins/squid.py index 4522cb3b..4544ef9a 100644 --- a/src/lib/sos/plugins/squid.py +++ b/src/lib/sos/plugins/squid.py @@ -15,7 +15,7 @@ import sos.plugintools class squid(sos.plugintools.PluginBase): - """This plugin gathers Squid related information + """squid related information """ def setup(self): self.addCopySpec("/etc/squid/squid.conf") diff --git a/src/lib/sos/plugins/ssh.py b/src/lib/sos/plugins/ssh.py index 5b9fd9cf..92a4c9e5 100644 --- a/src/lib/sos/plugins/ssh.py +++ b/src/lib/sos/plugins/ssh.py @@ -17,7 +17,7 @@ import sos.plugintools class ssh(sos.plugintools.PluginBase): - """This plugin gathers ssh-related information + """ssh-related information """ def setup(self): self.addCopySpec("/etc/ssh/ssh_config") diff --git a/src/lib/sos/plugins/startup.py b/src/lib/sos/plugins/startup.py index 29adf738..02361393 100644 --- a/src/lib/sos/plugins/startup.py +++ b/src/lib/sos/plugins/startup.py @@ -15,7 +15,7 @@ import sos.plugintools class startup(sos.plugintools.PluginBase): - """This plugin gathers startup information + """startup information """ def setup(self): self.addCopySpec("/etc/rc.d") diff --git a/src/lib/sos/plugins/system.py b/src/lib/sos/plugins/system.py index 06bf65d1..19d7859e 100644 --- a/src/lib/sos/plugins/system.py +++ b/src/lib/sos/plugins/system.py @@ -15,7 +15,7 @@ import sos.plugintools class system(sos.plugintools.PluginBase): - """This plugin gathers core system related information + """core system related information """ def setup(self): self.addCopySpec("/proc/sys") diff --git a/src/lib/sos/plugins/systemtap.py b/src/lib/sos/plugins/systemtap.py index 2020b260..c0609f4f 100644 --- a/src/lib/sos/plugins/systemtap.py +++ b/src/lib/sos/plugins/systemtap.py @@ -17,7 +17,7 @@ import sos.plugintools class systemtap(sos.plugintools.PluginBase): - """This plugin gathers SystemTap pre-requisites information + """SystemTap pre-requisites information """ def setup(self): # requires systemtap, systemtap-runtime, kernel-devel, diff --git a/src/lib/sos/plugins/x11.py b/src/lib/sos/plugins/x11.py index f7963eca..9b7b7ac9 100644 --- a/src/lib/sos/plugins/x11.py +++ b/src/lib/sos/plugins/x11.py @@ -15,7 +15,7 @@ import sos.plugintools class x11(sos.plugintools.PluginBase): - """This plugin gathers X related information + """X related information """ def setup(self): self.addCopySpec("/etc/X11") diff --git a/src/lib/sos/plugins/xen.py b/src/lib/sos/plugins/xen.py index ee225efd..d6daec63 100644 --- a/src/lib/sos/plugins/xen.py +++ b/src/lib/sos/plugins/xen.py @@ -17,6 +17,8 @@ import os, commands from stat import * class xen(sos.plugintools.PluginBase): + """Xen related information + """ def determineXenHost(self): if os.access("/proc/acpi/dsdt", os.R_OK): (status, output) = commands.getstatusoutput("/usr/bin/strings /proc/acpi/dsdt | grep -q int-xen") diff --git a/src/lib/sos/plugins/xinetd.py b/src/lib/sos/plugins/xinetd.py index f6ace143..715c831f 100644 --- a/src/lib/sos/plugins/xinetd.py +++ b/src/lib/sos/plugins/xinetd.py @@ -17,7 +17,7 @@ import sos.plugintools class xinetd(sos.plugintools.PluginBase): - """This plugin gathers xinetd information + """xinetd information """ def setup(self): self.addCopySpec("/etc/xinetd.conf") diff --git a/src/lib/sos/plugintools.py b/src/lib/sos/plugintools.py index 75ec033c..b403af4e 100644 --- a/src/lib/sos/plugintools.py +++ b/src/lib/sos/plugintools.py @@ -58,6 +58,7 @@ class PluginBase: self.copyPaths = [] self.collectProgs = [] self.thread = None + self.eta_weight = 1 # get the option list into a dictionary for opt in self.optionList: @@ -86,7 +87,7 @@ class PluginBase: except KeyboardInterrupt: raise KeyboardInterrupt except Exception, e: - self.cInfo['soslog'].warning("Problem at path %s (%s)\n" % (abspath,e)) + self.cInfo['soslog'].log(logging.VERBOSE, "Problem at path %s (%s)\n" % (abspath,e)) break return False @@ -142,7 +143,7 @@ class PluginBase: except KeyboardInterrupt: raise KeyboardInterrupt except Exception, e: - self.cInfo['soslog'].warning("Problem at path %s (%s)" % (srcpath+'/'+afile, e)) + self.cInfo['soslog'].log(logging.VERBOSE, "Problem at path %s (%s)" % (srcpath+'/'+afile, e)) # if on forbidden list, abspath is null if not abspath == '': dstslname = sosRelPath(self.cInfo['rptdir'], abspath) @@ -157,7 +158,7 @@ class PluginBase: except KeyboardInterrupt: raise KeyboardInterrupt except Exception, e: - self.cInfo['soslog'].debug("Problem at path %s (%s)" % (srcpath, e)) + self.cInfo['soslog'].log(logging.VERBOSE, "Problem at path %s (%s)" % (srcpath, e)) return abspath @@ -182,10 +183,9 @@ class PluginBase: """ try: # pylint: disable-msg = W0612 - status, shout, sherr, runtime = sosGetCommandOutput("/bin/cp --parents -P --preserve=mode,ownership,timestamps,links " + src +" " + self.cInfo['dstroot']) + status, shout, runtime = sosGetCommandOutput("/bin/cp --parents -P --preserve=mode,ownership,timestamps,links " + src +" " + self.cInfo['dstroot']) if status: self.cInfo['soslog'].debug(shout) - self.cInfo['soslog'].debug(sherr) abspath = os.path.join(self.cInfo['dstroot'], src.lstrip(os.path.sep)) relpath = sosRelPath(self.cInfo['rptdir'], abspath) return relpath, abspath @@ -194,7 +194,7 @@ class PluginBase: except KeyboardInterrupt: raise KeyboardInterrupt except Exception,e: - self.cInfo['soslog'].error("Problem copying file %s (%s)" % (src, e)) + self.cInfo['soslog'].warning("Problem copying file %s (%s)" % (src, e)) def addForbiddenPath(self, forbiddenPath): """Specify a path to not copy, even if it's part of a copyPaths[] entry. @@ -276,7 +276,7 @@ class PluginBase: self.cInfo['soslog'].log(logging.VERBOSE, "binary '%s' does not exist or is not runnable" % prog.split()[0]) # pylint: disable-msg = W0612 - status, shout, sherr, runtime = sosGetCommandOutput(prog) + status, shout, runtime = sosGetCommandOutput(prog) return status def runExe(self, exe): @@ -295,17 +295,9 @@ class PluginBase: def makeCommandFilename(self, exe): """ The internal function to build up a filename based on a command """ # build file name for output - rawcmd = os.path.basename(exe).strip()[:28] + rawcmd = os.path.basename(exe).strip() - # Mangle command to make it suitable for a file name - tabl = string.maketrans(" /\t;#$|%\"'`}{\n", "--------------") - mangledname = rawcmd.translate(tabl) - - # remove double "--" - while True: - doublepos = mangledname.find("--") - if doublepos == -1: break - mangledname = mangledname[:doublepos] + mangledname[doublepos+2:] + mangledname = re.sub(r"[^\w-]+", "_", rawcmd)[0:32] outfn = self.cInfo['cmddir'] + "/" + self.piName + "/" + mangledname @@ -325,7 +317,7 @@ class PluginBase: return # pylint: disable-msg = W0612 - status, shout, sherr, runtime = sosGetCommandOutput(exe) + status, shout, runtime = sosGetCommandOutput(exe) if suggest_filename: outfn = self.makeCommandFilename(suggest_filename) @@ -343,21 +335,12 @@ class PluginBase: # FIXME: use python's internal commands os.system('cd "%s" && ln -s "%s" "%s"' % (self.cInfo['dstroot'], outfn[len(self.cInfo['dstroot'])+1:], root_symlink)) - if len(sherr) > 0: - errfn = outfn + ".err" - outfd = open(errfn, "w") - outfd.write(sherr) - outfd.close() - errfn = errfn[len(self.cInfo['cmddir'] + "/" ):] - self.cInfo['soslog'].debug(sherr) - else: - errfn = None outfn = outfn[len(self.cInfo['cmddir'])+1:] # sosStatus(status) # save info for later self.executedCommands.append({'exe': exe, 'file':outfn}) # save in our list - self.cInfo['xmlreport'].add_command(cmdline=exe,exitcode=status,f_stdout=outfn,f_stderr=errfn,runtime=runtime) + self.cInfo['xmlreport'].add_command(cmdline=exe,exitcode=status,f_stdout=outfn,runtime=runtime) return outfn def writeTextToCommand(self, exe, text): @@ -402,11 +385,12 @@ class PluginBase: self.thread = Thread(target=self.copyStuff, name=self.piName+'-thread') self.thread.start() - def wait(self): + def wait(self,timeout=None): """ wait for a thread to complete - only called for threaded execution """ - self.thread.join() + self.thread.join(timeout) + return self.thread.isAlive() def copyStuff(self): """ diff --git a/src/lib/sos/policyredhat.py b/src/lib/sos/policyredhat.py index 34177347..e31900d7 100755 --- a/src/lib/sos/policyredhat.py +++ b/src/lib/sos/policyredhat.py @@ -80,7 +80,11 @@ class SosPolicy: name = raw_input("Please enter your first initial and last name [%s]: " % localname) if len(name) == 0: name = localname - ticketNumber = raw_input("Please enter the case number that you are generating this report for: ") + try: + ticketNumber = raw_input("Please enter the case number that you are generating this report for: ") + except KeyboardInterrupt: + print "<interrupted>" + print if len(ticketNumber): namestr = name + "." + ticketNumber @@ -108,9 +112,10 @@ class SosPolicy: os.chdir(ourtempdir) oldmask = os.umask(077) # pylint: disable-msg = W0612 - status, shout, sherr, runtime = sosGetCommandOutput(tarcmd) + status, shout, runtime = sosGetCommandOutput(tarcmd) os.umask(oldmask) os.chdir(curwd) + # FIXME: use python internal command os.system("/bin/mv %s %s" % (aliasdir, self.cInfo['dstroot'])) sys.stdout.write("\n") diff --git a/src/sosreport b/src/sosreport index b00dfd6a..5858d719 100755 --- a/src/sosreport +++ b/src/sosreport @@ -36,7 +36,7 @@ from threading import Thread, activeCount, enumerate import signal import logging from stat import * -from time import strftime, localtime +from time import strftime, localtime, time from pwd import getpwuid __version__ = 1.7 @@ -53,7 +53,8 @@ def doExitCode(): if ( ( activeCount() > 1 ) and ( __breakHits__ == 1 ) ): print "SIGTERM received, multiple threads detected, waiting for all threads to exit" for thread in enumerate(): - thread.wait() + if thread.getName() != "MainThread": + thread.join() print "All threads ended, cleaning up." if ( ( activeCount() > 1 ) and ( __breakHits__ > 1 ) ): print "Multiple SIGTERMs, multiple threads, attempting to signal threads to die immediately" @@ -121,15 +122,15 @@ __cmdParser__.add_option("-k", "--pluginopts", action="extend", \ __cmdParser__.add_option("-v", "--verbose", action="count", \ dest="verbosity", \ help="How obnoxious we're being about telling the user what we're doing.") -__cmdParser__.add_option("-b", "--no-progressbar", action="store_false", \ - dest="progressbar", default=True, \ - help="Do not display a progress bar.") -__cmdParser__.add_option("-c", "--curses", action="store_false", \ +__cmdParser__.add_option("-c", "--curses", action="store_true", \ dest="use_curses", default=False, \ + help="Display a text GUI menu to modify plugin options.") +__cmdParser__.add_option("--no-progressbar", action="store_false", \ + dest="progressbar", default=True, \ help="Do not display a progress bar.") -__cmdParser__.add_option("-m", "--multithreaded", action="store_true", \ +__cmdParser__.add_option("--no-multithread", action="store_false", \ dest="multithread", \ - help="Use the multithreaded information gathering mode to speed up the report (experimental)") + help="Disable multithreaded gathering mode to speed up the report", default=False) (__cmdLineOpts__, __cmdLineArgs__)=__cmdParser__.parse_args() def get_curse_options(alloptions): @@ -191,21 +192,38 @@ class progressBar: self.progBar = "[]" # This holds the progress bar string self.min = minValue self.max = maxValue - self.span = maxValue - minValue self.width = totalWidth - self.amount = 0 # When amount == max, we are 100% done + self.time_start = time() + self.amount = 0 # When amount == max, we are 100% done + self.eta = 0 + self.last_amount_update = time() self.updateAmount(0) # Build progress bar string def updateAmount(self, newAmount = 0): if newAmount < self.min: newAmount = self.min if newAmount > self.max: newAmount = self.max - self.amount = newAmount - - # Figure out the new percent done, round to an integer - diffFromMin = float(self.amount - self.min) - percentDone = (diffFromMin / float(self.span)) * 100.0 - percentDone = round(percentDone) - percentDone = int(percentDone) + if self.amount != newAmount: + self.last_amount_update = time() + self.amount = newAmount + last_update_relative = round(self.last_amount_update - self.time_start) + self.eta = round(last_update_relative * self.max / self.amount) + + # generate ETA + timeElapsed = round(time() - self.time_start) + last_update_relative = round(self.last_amount_update - self.time_start) + if timeElapsed >= 10: + percentDone = round(timeElapsed * 100 / self.eta) + if percentDone > 100: + percentDone = 100 + ETA = timeElapsed + elif self.eta < timeElapsed: + ETA = timeElapsed + else: + ETA = self.eta + ETA = "[%02d:%02d/%02d:%02d]" % (round(timeElapsed/60), timeElapsed % 60, round(ETA/60), ETA % 60) + else: + ETA = "[%02d:%02d/--:--]" % (round(timeElapsed/60), timeElapsed % 60) + percentDone = 0 # Figure out how many hash bars the percentage should be allFull = self.width - 2 @@ -220,7 +238,7 @@ class progressBar: percentString = str(percentDone) + "%" # slice the percentage into the bar - self.progBar = " Progress" + self.progBar[0:percentPlace] + percentString + self.progBar[percentPlace+len(percentString):] + self.progBar = " Progress" + self.progBar[0:percentPlace] + percentString + self.progBar[percentPlace+len(percentString):] + ETA def incAmount(self, toInc = 1): self.updateAmount(self.amount+toInc) @@ -231,6 +249,7 @@ class progressBar: sys.stdout.flush() def update(self): + self.updateAmount(self.amount) sys.stdout.write(self.progBar + '\r') sys.stdout.flush() @@ -478,7 +497,7 @@ Press ENTER to continue, or CTRL-C to quit. print sys.exit(0) - # Iterate over plugins for each stage + # setup plugin options if __cmdLineOpts__.plugopts: opts = {} for opt in __cmdLineOpts__.plugopts: @@ -516,15 +535,21 @@ Press ENTER to continue, or CTRL-C to quit. # Setup the progress bar if __cmdLineOpts__.progressbar: - pbar = progressBar(0, len(loadedplugins) * 33, totalWidth = 60) + pbar = progressBar(0, len(loadedplugins), totalWidth = 60) # Call the setup method for each plugin for plugname, plug in loadedplugins: soslog.log(logging.VERBOSE2, "Setting up plugin module %s" % plugname) plug.setup() - if __cmdLineOpts__.progressbar: - pbar.incAmount() - pbar.update() + if __cmdLineOpts__.progressbar: + pbar.incAmount() + pbar.update() + + # gather information useful for generating ETA + eta_weight = 0 + for plugname, plug in loadedplugins: + eta_weight += plug.eta_weight + pbar.max = eta_weight # Call the collect method for each plugin for plugname, plug in loadedplugins: @@ -533,23 +558,29 @@ Press ENTER to continue, or CTRL-C to quit. plug.doCollect() else: plug.copyStuff() - if __cmdLineOpts__.progressbar: - if __cmdLineOpts__.multithread: - pbar.incAmount() - else: - pbar.incAmount(30) - pbar.update() - - xmlrep.serialize_to_file(rptdir + "/" + "sosreport.xml") + if __cmdLineOpts__.progressbar: + pbar.incAmount(plug.eta_weight) + pbar.update() # Wait for all the collection threads to exit if __cmdLineOpts__.multithread: - for plugname, plug in loadedplugins: - soslog.log(logging.VERBOSE2, "Waiting for plugin %s to return" % plugname) - plug.wait() + finishedplugins = [] + while len(loadedplugins) > 0: + plugname, plug = loadedplugins.pop(0) + if not plug.wait(0.2): + finishedplugins.append((plugname,plug)) + soslog.log(logging.VERBOSE2, "plugin %s has returned" % plugname) + if __cmdLineOpts__.progressbar: + pbar.incAmount(plug.eta_weight) + else: + soslog.log(logging.VERBOSE3, "plugin %s still hasn't returned" % plugname) + loadedplugins.append((plugname,plug)) if __cmdLineOpts__.progressbar: - pbar.incAmount(30) pbar.update() + loadedplugins = finishedplugins + del finishedplugins + + xmlrep.serialize_to_file(rptdir + "/" + "sosreport.xml") # Call the analyze method for each plugin for plugname, plug in loadedplugins: |