From f21d141f346afce9f0dab6d9ebc246986311a048 Mon Sep 17 00:00:00 2001 From: shnavid Date: Thu, 2 Aug 2007 14:27:28 +0000 Subject: Merged navid-dev r306 into the trunk git-svn-id: svn+ssh://svn.fedorahosted.org/svn/sos/trunk@307 ef72aa8b-4018-0410-8976-d6e080ef94d8 --- src/TODO | 6 +- src/lib/sos/helpers.py | 12 ++-- src/lib/sos/plugins/amd.py | 1 - src/lib/sos/plugins/cluster.py | 10 ++- src/lib/sos/plugins/devicemapper.py | 2 + src/lib/sos/plugins/hardware.py | 5 ++ src/lib/sos/plugins/kernel.py | 4 +- src/lib/sos/plugins/networking.py | 10 ++- src/lib/sos/plugins/process.py | 10 +-- src/lib/sos/plugins/sendmail.py | 1 - src/lib/sos/plugins/ssh.py | 1 - src/lib/sos/plugins/xinetd.py | 9 ++- src/lib/sos/plugins/yum.py | 26 ++++--- src/lib/sos/plugintools.py | 3 +- src/lib/sos/policyredhat.py | 62 +++++++++-------- src/locale/en/LC_MESSAGES/sos.po | 4 +- src/locale/fr/LC_MESSAGES/sos.po | 134 ++++++++++++++++++++++++++++++++++++ src/locale/it/LC_MESSAGES/sos.po | 4 +- src/setup.py | 2 +- src/sos.spec | 5 +- src/sosreport | 109 ++++++++++++++++++----------- src/sosreport.1 | 58 ++++++++-------- 22 files changed, 335 insertions(+), 143 deletions(-) create mode 100644 src/locale/fr/LC_MESSAGES/sos.po (limited to 'src') diff --git a/src/TODO b/src/TODO index 2f2d323f..fd3c8f38 100644 --- a/src/TODO +++ b/src/TODO @@ -1,5 +1,7 @@ To Do List: + * --batch option + * Gather statistics (time, files collected, commands run) per plugin * Choose sane defaults to satisfy Red Hat support requirements (ie. what @@ -7,12 +9,8 @@ To Do List: * Display on screen what files/commands are being gathered. - * Make sosreport a drop-in replacement for sysreport - * Allow to use a different rootdir than / - * Add support for distributions other than Fedora. - * Make it easier to select a policy module and perhaps optionally include plugins from the library, to allow per-distribution customization. diff --git a/src/lib/sos/helpers.py b/src/lib/sos/helpers.py index dcff1405..bcdee6fb 100755 --- a/src/lib/sos/helpers.py +++ b/src/lib/sos/helpers.py @@ -59,13 +59,15 @@ def makeNonBlocking(afd): def sosGetCommandOutput(command): """ Execute a command and gather stdin, stdout, and return status. - Adapted from Python Cookbook - O'Reilly """ stime = time() - errdata = '' - status,outdata=commands.getstatusoutput(command) - return (status, outdata, time()-stime) - + inpipe, pipe = os.popen4(command, 'r') + inpipe.close() + text = pipe.read() + sts = pipe.close() + if sts is None: sts = 0 + if text[-1:] == '\n': text = text[:-1] + return (sts, text, time()-stime) # FIXME: this needs to be made clean and moved to the plugin tools, so # that it prints nice color output like sysreport if the progress bar diff --git a/src/lib/sos/plugins/amd.py b/src/lib/sos/plugins/amd.py index 174f850b..a8e6ae13 100644 --- a/src/lib/sos/plugins/amd.py +++ b/src/lib/sos/plugins/amd.py @@ -32,6 +32,5 @@ class amd(sos.plugintools.PluginBase): self.collectExtOutput("/bin/rpm -qV am-utils") self.collectExtOutput("/bin/egrep -e 'automount|pid.*nfs' /proc/mounts") self.collectExtOutput("/bin/mount | egrep -e 'automount|pid.*nfs'") - self.collectExtOutput("/sbin/chkconfig --list amd") return diff --git a/src/lib/sos/plugins/cluster.py b/src/lib/sos/plugins/cluster.py index 62315bc6..a996d362 100644 --- a/src/lib/sos/plugins/cluster.py +++ b/src/lib/sos/plugins/cluster.py @@ -54,6 +54,7 @@ class cluster(sos.plugintools.PluginBase): try: rhelver = self.cInfo["policy"].pkgDictByName("redhat-release")[0] except: rhelver = None + # FIXME: we should only run tests specific for the version, now just do them all regardless if rhelver == "4" or True: # check that kernel module packages are installed for # running kernel version @@ -164,7 +165,7 @@ class cluster(sos.plugintools.PluginBase): # check for fs exported via nfs without nfsid attribute if len(xpathContext.xpathEval("/cluster/rm/service//fs[not(@fsid)]/nfsexport")): - self.addDiagnose("one or more nfs file-system doesn't have a fsid attribute set.") + self.addDiagnose("one or more nfs export do not have a fsid attribute set.") # cluster.conf file version and the in-memory cluster configuration version matches status, cluster_version = commands.getstatusoutput("cman_tool status | grep 'Config version'") @@ -207,6 +208,8 @@ class cluster(sos.plugintools.PluginBase): self.collectExtOutput("/usr/bin/openais-cfgtool -s") self.collectExtOutput("/usr/bin/clustat") + self.collectExtOutput("/sbin/ipvsadm -L", root_symlink = "ipvsadm_-L") + if self.isOptionEnabled('gfslockdump'): self.do_gfslockdump() if self.isOptionEnabled('lockdump'): self.do_lockdump() if self.isOptionEnabled('taskdump'): self.do_taskdump() @@ -226,7 +229,10 @@ class cluster(sos.plugintools.PluginBase): self.addCopySpec("/var/log/messages") def do_lockdump(self): - fp = open("/proc/cluster/services","r") + try: + fp = open("/proc/cluster/services","r") + except: + return for line in fp.readlines(): if line[0:14] == "DLM Lock Space": try: diff --git a/src/lib/sos/plugins/devicemapper.py b/src/lib/sos/plugins/devicemapper.py index e517aa3d..a670cae7 100644 --- a/src/lib/sos/plugins/devicemapper.py +++ b/src/lib/sos/plugins/devicemapper.py @@ -22,6 +22,8 @@ class devicemapper(sos.plugintools.PluginBase): self.collectExtOutput("/sbin/dmsetup table") self.collectExtOutput("/sbin/dmsetup status") + self.collectExtOutput("/usr/bin/systool -v -C -b scsi") + self.collectExtOutput("/usr/sbin/vgscan -vvv") self.collectExtOutput("/usr/sbin/vgdisplay -vv", root_symlink = "vgdisplay") self.collectExtOutput("/usr/sbin/pvscan -v") diff --git a/src/lib/sos/plugins/hardware.py b/src/lib/sos/plugins/hardware.py index f8eeda88..dc1d4a2c 100644 --- a/src/lib/sos/plugins/hardware.py +++ b/src/lib/sos/plugins/hardware.py @@ -38,6 +38,11 @@ class hardware(sos.plugintools.PluginBase): self.collectExtOutput("/usr/share/rhn/up2dateclient/hardware.py") 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") + 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.'") diff --git a/src/lib/sos/plugins/kernel.py b/src/lib/sos/plugins/kernel.py index 9a752c13..aab7d7f5 100644 --- a/src/lib/sos/plugins/kernel.py +++ b/src/lib/sos/plugins/kernel.py @@ -19,7 +19,7 @@ class kernel(sos.plugintools.PluginBase): """kernel related information """ optionList = [("modinfo", 'gathers module information on all modules', 'fast', True), - ('sysrq', 'trigger SysRq+t dumps', 'fast', False)] + ('sysrq', 'trigger sysrq+[m,p,t] dumps', 'fast', False)] moduleFile = "" taintList = [ {'regex':'mvfs*', 'description':'Clearcase module'}, @@ -56,6 +56,7 @@ class kernel(sos.plugintools.PluginBase): runcmd = runcmd + " " + kmod if len(runcmd): self.collectExtOutput("/sbin/modinfo " + runcmd) + self.collectExtOutput("/sbin/sysctl -a") self.collectExtOutput("/sbin/ksyms") self.addCopySpec("/sys/module") self.addCopySpec("/proc/filesystems") @@ -67,7 +68,6 @@ class kernel(sos.plugintools.PluginBase): self.addCopySpec("/etc/conf.modules") self.addCopySpec("/etc/modules.conf") self.addCopySpec("/etc/modprobe.conf") - self.collectExtOutput("/usr/sbin/dmidecode", root_symlink = "dmidecode") self.collectExtOutput("/usr/sbin/dkms status") self.addCopySpec("/proc/cmdline") self.addCopySpec("/proc/driver") diff --git a/src/lib/sos/plugins/networking.py b/src/lib/sos/plugins/networking.py index b7331849..1a450aaa 100644 --- a/src/lib/sos/plugins/networking.py +++ b/src/lib/sos/plugins/networking.py @@ -50,6 +50,7 @@ class networking(sos.plugintools.PluginBase): self.writeTextToCommand(cmd,"IPTables module "+tablename+" not loaded\n") def setup(self): + self.addCopySpec("/proc/net") self.addCopySpec("/etc/nsswitch.conf") self.addCopySpec("/etc/yp.conf") self.addCopySpec("/etc/inetd.conf") @@ -63,13 +64,16 @@ class networking(sos.plugintools.PluginBase): self.collectIPTable("filter") self.collectIPTable("nat") self.collectIPTable("mangle") - self.collectExtOutput("/bin/netstat -nap") + self.collectExtOutput("/bin/netstat -s") + self.collectExtOutput("/bin/netstat -neopa", root_symlink = "netstat") + self.collectExtOutput("/sbin/ip link") + self.collectExtOutput("/sbin/ip address") + self.collectExtOutput("/sbin/ifenslave -a") if ifconfigFile: for eth in self.get_interface_name(ifconfigFile): self.collectExtOutput("/sbin/ethtool "+eth) if self.isOptionEnabled("traceroute"): - # The semicolon prevents the browser from thinking this is a link when viewing the report - self.collectExtOutput("/bin/traceroute rhn.redhat.com;") + self.collectExtOutput("/bin/traceroute -n rhn.redhat.com") return diff --git a/src/lib/sos/plugins/process.py b/src/lib/sos/plugins/process.py index baa185b4..ce4ef227 100644 --- a/src/lib/sos/plugins/process.py +++ b/src/lib/sos/plugins/process.py @@ -21,7 +21,9 @@ class process(sos.plugintools.PluginBase): """process information """ def setup(self): - self.collectExtOutput("/bin/ps auxww", root_symlink = "ps") + self.collectExtOutput("/bin/ps auxwww", root_symlink = "ps") + self.collectExtOutput("/bin/ps auxwwwm") + self.collectExtOutput("/bin/ps alxwww") self.collectExtOutput("/usr/bin/pstree", root_symlink = "pstree") return @@ -38,11 +40,11 @@ class process(sos.plugintools.PluginBase): line = line.split() if line[0] == "D": # keep an eye on the process to see if the stat changes - for inc in range(1,10): + for inc in range(1,5): try: if len(self.fileGrep("^State: D", " /proc/%d/status" % int(line[1]))) == 0: # status is not D, good. let's get out of the loop. - time.sleep(0.1) + time.sleep(0.1 * inc) continue except IOError: # this should never happen... @@ -55,7 +57,7 @@ class process(sos.plugintools.PluginBase): # realpath if len(dpids): - self.addDiagnose("one or more processes are in state D") + self.addDiagnose("one or more processes are in state D (sosreport might hang)") return diff --git a/src/lib/sos/plugins/sendmail.py b/src/lib/sos/plugins/sendmail.py index 79713805..76b40905 100644 --- a/src/lib/sos/plugins/sendmail.py +++ b/src/lib/sos/plugins/sendmail.py @@ -28,6 +28,5 @@ class sendmail(sos.plugintools.PluginBase): def setup(self): self.addCopySpec("/etc/mail/*") self.addCopySpec("/var/log/maillog") - self.collectExtOutput("/sbin/chkconfig --list sendmail") return diff --git a/src/lib/sos/plugins/ssh.py b/src/lib/sos/plugins/ssh.py index 92a4c9e5..6352583b 100644 --- a/src/lib/sos/plugins/ssh.py +++ b/src/lib/sos/plugins/ssh.py @@ -22,6 +22,5 @@ class ssh(sos.plugintools.PluginBase): def setup(self): self.addCopySpec("/etc/ssh/ssh_config") self.addCopySpec("/etc/ssh/sshd_config") - self.collectExtOutput("/sbin/chkconfig --list sshd") return diff --git a/src/lib/sos/plugins/xinetd.py b/src/lib/sos/plugins/xinetd.py index 715c831f..f5292fb5 100644 --- a/src/lib/sos/plugins/xinetd.py +++ b/src/lib/sos/plugins/xinetd.py @@ -15,13 +15,18 @@ ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. import sos.plugintools +import os class xinetd(sos.plugintools.PluginBase): """xinetd information """ + def checkenabled(self): + if self.cInfo["policy"].pkgByName("xinetd") or os.path.exists("/etc/xinetd.conf"): + return True + return False + def setup(self): self.addCopySpec("/etc/xinetd.conf") - self.addCopySpec("/etc/xinetd.d/*") - self.collectExtOutput("/sbin/chkconfig --list xinetd") + self.addCopySpec("/etc/xinetd.d") return diff --git a/src/lib/sos/plugins/yum.py b/src/lib/sos/plugins/yum.py index 89102c38..2ba5693f 100644 --- a/src/lib/sos/plugins/yum.py +++ b/src/lib/sos/plugins/yum.py @@ -18,20 +18,24 @@ class yum(sos.plugintools.PluginBase): """yum information """ - def defaultenabled(self): - # enable with -e or -o + optionList = [("yumlist", "list repositories and packages", "slow", False)] + + def checkenabled(self): + if self.cInfo["policy"].pkgByName("yum") or os.path.exists("/etc/yum.conf"): + return True return False def setup(self): - # Pull all yum related information + # Pull all yum related information self.addCopySpec("/etc/yum") - self.addCopySpec("/etc/yum.repos.d") - self.addCopySpec("/etc/yum.conf") - self.addCopySpec("/var/log/yum.log") - - # Get a list of channels the machine is subscribed to. - self.collectExtOutput("/bin/echo \"repo list\" | /usr/bin/yum shell") - # List various information about available packages - self.collectExtOutput("/usr/bin/yum list") + self.addCopySpec("/etc/yum.repos.d") + self.addCopySpec("/etc/yum.conf") + self.addCopySpec("/var/log/yum.log") + + if self.isOptionEnabled("yumlist"): + # Get a list of channels the machine is subscribed to. + self.collectExtOutput("/bin/echo \"repo list\" | /usr/bin/yum shell") + # List various information about available packages + self.collectExtOutput("/usr/bin/yum list") return diff --git a/src/lib/sos/plugintools.py b/src/lib/sos/plugintools.py index f58c8151..8809100f 100644 --- a/src/lib/sos/plugintools.py +++ b/src/lib/sos/plugintools.py @@ -173,7 +173,6 @@ class PluginBase: try: dstslname, abspath = self.__copyFile(srcpath) self.copiedFiles.append({'srcpath':srcpath, 'dstpath':dstslname, 'symlink':"yes", 'pointsto':link}) - self.cInfo['xmlreport'].add_file(srcpath,os.stat(srcpath)) except SystemExit: raise SystemExit except KeyboardInterrupt: @@ -581,7 +580,7 @@ class PluginBase: html = html + "

Commands Executed:

\n" diff --git a/src/lib/sos/policyredhat.py b/src/lib/sos/policyredhat.py index 69c48e0f..fbcc32c2 100755 --- a/src/lib/sos/policyredhat.py +++ b/src/lib/sos/policyredhat.py @@ -21,10 +21,11 @@ import os import commands import sys import string -import re from tempfile import gettempdir from sos.helpers import * import random +import re +import md5 SOME_PATH = "/tmp/SomePath" @@ -94,15 +95,15 @@ class SosPolicy: return ret def runlevelDefault(self): - inittab=os.path.isfile('/etc/inittab') - if inittab is True: - f=open(inittab,'r') + try: + f=open("/etc/inittab",'r') content=f.read() f.close() reg=re.compile(r"^id:(\d{1}):initdefault:\D",re.MULTILINE) for initlevel in reg.findall(content): return initlevel - else: return 3 + except: + return 3 def kernelVersion(self): return commands.getoutput("/bin/uname -r").strip("\n") @@ -117,26 +118,30 @@ class SosPolicy: name = "-".join(fields[:-3]) return (name, version, release, arch) - def packageResults(self): + def preWork(self): + # this method will be called before the gathering begins + localname = commands.getoutput("/bin/uname -n").split(".")[0] try: - name = raw_input("Please enter your first initial and last name [%s]: " % localname) - name = re.sub(r"[^a-zA-Z.0-9]", "", name) - if len(name) == 0: name = localname + 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 - ticketNumber = raw_input("Please enter the case number that you are generating this report for: ") - ticketNumber = re.sub(r"[^0-9]", "", ticketNumber) + 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 KeyboardInterrupt: - print _("") - print _("Temporary files have been stored in %s") % self.cInfo['dstroot'] print - sys.exit(1) + sys.exit(0) - if len(ticketNumber): - namestr = name + "." + ticketNumber + def packageResults(self): + + if len(self.ticketNumber): + namestr = self.reportName + "." + self.ticketNumber else: - namestr = name + namestr = self.reportName ourtempdir = gettempdir() tarballName = os.path.join(ourtempdir, "sosreport-" + namestr + ".tar.bz2") @@ -148,7 +153,7 @@ class SosPolicy: tarcmd = "/bin/tar -jcf %s %s" % (tarballName, namestr) print - print "Creating compressed tar archive..." + print "Creating compressed archive..." if not os.access(string.split(tarcmd)[0], os.X_OK): print "Unable to create tarball" return @@ -166,17 +171,16 @@ class SosPolicy: os.system("/bin/mv %s %s" % (aliasdir, self.cInfo['dstroot'])) # add last 6 chars from md5sum to file name - status, md5out = commands.getstatusoutput('''/usr/bin/md5sum "%s"''' % tarballName) - if not status and len(md5out): - oldtarballName = tarballName - try: - md5out = md5out.strip().split()[0] - tarballName = os.path.join(ourtempdir, "sosreport-%s-%s.tar.bz2" % (namestr, md5out[-6:]) ) - os.system("/bin/mv %s %s" % (oldtarballName, tarballName) ) - except: - md5out = False - else: - md5out = False + fp = open(tarballName, "r") + md5out = md5.new(fp.read()).hexdigest() + fp.close() + oldtarballName = tarballName + tarballName = os.path.join(ourtempdir, "sosreport-%s-%s.tar.bz2" % (namestr, md5out[-6:]) ) + os.system("/bin/mv %s %s" % (oldtarballName, tarballName) ) + # store md5 to a file + fp = open(tarballName + ".md5", "w") + fp.write(md5out + "\n") + fp.close() sys.stdout.write("\n") print "Your sosreport has been generated and saved in:\n %s" % tarballName diff --git a/src/locale/en/LC_MESSAGES/sos.po b/src/locale/en/LC_MESSAGES/sos.po index c103a495..d65c8f78 100644 --- a/src/locale/en/LC_MESSAGES/sos.po +++ b/src/locale/en/LC_MESSAGES/sos.po @@ -24,7 +24,7 @@ msgid "plugin %s does not validate, skipping" msgstr "" #: sosreport:421 -msgid "plug %s skipped (noplugins)" +msgid "plug %s skipped (--skip-plugins)" msgstr "" #: sosreport:425 @@ -32,7 +32,7 @@ msgid "plugin %s is inactive (use -e or -o to enable)." msgstr "" #: sosreport:433 -msgid "plugin %s not specified in --onlyplugin list" +msgid "plugin %s not specified in --only-plugins list" msgstr "" #: sosreport:438 diff --git a/src/locale/fr/LC_MESSAGES/sos.po b/src/locale/fr/LC_MESSAGES/sos.po new file mode 100644 index 00000000..5ed0789f --- /dev/null +++ b/src/locale/fr/LC_MESSAGES/sos.po @@ -0,0 +1,134 @@ +# sosreport Fench translation file +# Copyright (C) Red Hat UK, Ltd. +# Imed Chihi , 2007. +# +msgid "" +msgstr "" +"Project-Id-Version: sos 1.7\n" +"POT-Creation-Date: 2007-08-02 10:20\n" +"PO-Revision-Date: 2007-08-02 13:00+01\n" +"Last-Translator: Imed Chihi \n" +"Language-Team: FR \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: utf-8\n" +"Generated-By: pygettext.py 1.5\n" + + +#: sosreport:370 +msgid "sosreport (version %s)" +msgstr "" + +#: sosreport:388 +msgid "plugin %s does not validate, skipping" +msgstr "plugin %s ne s'applique pas, desactivé" + +#: sosreport:392 +msgid "plug %s skipped (--skip-plugins)" +msgstr "plugin %s desactivé (--skip-plugins)" + +#: sosreport:396 +msgid "plugin %s is inactive (use -e or -o to enable)." +msgstr "plugin %s a été desactivé (utiliser -e ou -o pour réactiver)." + +#: sosreport:404 +msgid "plugin %s not specified in --only-plugins list" +msgstr "plugin %s non specifié dans la liste --only-plugins" + +#: sosreport:409 +msgid "plugin %s does not install, skipping" +msgstr "Plugin %s ne s'installe pas, déscativé" + +#: sosreport:412 +msgid "could not load plugin %s" +msgstr "Echec du chargement du plugin %s" + +#: sosreport:455 +msgid "processing options from plugin: %s" +msgstr "Traitement des options du plugin: %s" + +#: sosreport:466 +msgid "no valid plugins found" +msgstr "Aucun plugin valide trouvé" + +#: sosreport:471 +msgid "The following plugins are currently enabled:" +msgstr "Les plugins suivants sont actuellement activés:" + +#: sosreport:476 +msgid "No plugin enabled." +msgstr "Aucun plugin activé." + +#: sosreport:480 +msgid "The following plugins are currently disabled:" +msgstr "Les plugins suivants sont actuellment déscativés:" + +#: sosreport:487 +msgid "The following plugin options are available:" +msgstr "Les options de plugin suivantes sont disponibles:" + +#: sosreport:507 +msgid "No plugin options available." +msgstr "Pas d'options de plugin configurables." + +#: sosreport:515 +msgid "sosreport requires root permissions to run." +msgstr "sosreport doit être lancé avec les privilèges root." + +#: sosreport:522 +msgid "no valid plugins were enabled" +msgstr "Aucun plugin valide n'a été activé" + +#: sosreport:526 +msgid "" +"This utility will collect some detailed information about the\n" +"hardware and setup of your Red Hat Enterprise Linux system.\n" +"The information is collected and an archive is packaged under\n" +"/tmp, which you can send to a support rappresentative.\n" +"Red Hat will use this information for diagnostic purposes ONLY\n" +"and it will be considered confidential information.\n" +"\n" +"This process may take a while to complete.\n" +"No changes will be made to your system.\n" +"\n" +"Press ENTER to continue, or CTRL-C to quit.\n" +msgstr "" +"Cet outil va collecter des informations détaillées sur le matériel\n" +"et la configuration de votre système Red Hat Enterprise Linux.\n" +"Les informations seront assemblées dans une archive sous /tmp,\n" +"que vous pouvez renvoyer à un représentant du Support Red Hat.\n" +"Red Hat utilisera ces informations à fin d'anaylser les problèmes UNIQUEMENT\n" +"et elles seront considérées comme confidentielles.\n" +"\n" +"Ce processus pourrait prendre du temps pour finir.\n" +"Aucun changement ne sera apporté à votre système.\n" +"\n" +"Tapez ENTREE pour continuer, ou CTRL-C pour quitter.\n.\n" + +#: sosreport:555 +msgid "One or more plugins have detected a problem in your configuration." +msgstr "Un ou plusieurs plugins ont détecté un problème avec votre configuration." + +#: sosreport:556 +msgid "Please review the following messages:" +msgstr "Prière de vérifier les messages suivants:" + +#: sosreport:571 +msgid "Are you sure you would like to continue (y/n) ? " +msgstr "Voulez vous continuer (y/n)?" + +#: sosreport:572 +msgid "Y" +msgstr "O" + +#: sosreport:572 +msgid "y" +msgstr "o" + +#: sosreport:575 +msgid "N" +msgstr "N" + +#: sosreport:575 +msgid "n" +msgstr "n" diff --git a/src/locale/it/LC_MESSAGES/sos.po b/src/locale/it/LC_MESSAGES/sos.po index 0b5e2b32..23ad3a13 100644 --- a/src/locale/it/LC_MESSAGES/sos.po +++ b/src/locale/it/LC_MESSAGES/sos.po @@ -24,7 +24,7 @@ msgid "plugin %s does not validate, skipping" msgstr "" #: sosreport:421 -msgid "plug %s skipped (noplugins)" +msgid "plug %s skipped (--skip-plugins)" msgstr "" #: sosreport:425 @@ -32,7 +32,7 @@ msgid "plugin %s is inactive (use -e or -o to enable)." msgstr "" #: sosreport:433 -msgid "plugin %s not specified in --onlyplugin list" +msgid "plugin %s not specified in --only-plugins list" msgstr "" #: sosreport:438 diff --git a/src/setup.py b/src/setup.py index 26504147..6e36050d 100644 --- a/src/setup.py +++ b/src/setup.py @@ -9,6 +9,6 @@ setup( packages = ['sos', 'sos.plugins'], scripts = [], package_dir = {'': 'lib',}, - data_files = [ ('/usr/sbin', ['sosreport']), ('/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']) + data_files = [ ('/usr/sbin', ['sosreport']), ('/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']) ] ) diff --git a/src/sos.spec b/src/sos.spec index 1c979f58..a8238f8f 100644 --- a/src/sos.spec +++ b/src/sos.spec @@ -2,7 +2,7 @@ %define name sos %define version 1.7 -%define release 3 +%define release 5 %define _localedir %_datadir/locale @@ -22,6 +22,7 @@ BuildArch: noarch Url: http://sos.108.redhat.com/ BuildRequires: python-devel Requires: libxml2-python +Obsoletes: sysreport %description Sos is a set of tools that gathers information about system @@ -38,6 +39,7 @@ python setup.py build %install rm -rf ${RPM_BUILD_ROOT} python setup.py install --optimize 1 --root=$RPM_BUILD_ROOT +ln -s /usr/sbin/sosreport $RPM_BUILD_ROOT/usr/sbin/sysreport %clean rm -rf ${RPM_BUILD_ROOT} @@ -45,6 +47,7 @@ rm -rf ${RPM_BUILD_ROOT} %files %defattr(-,root,root,-) %{_sbindir}/sosreport +/usr/sbin/sysreport %{python_sitelib}/sos/ %{_mandir}/man1/sosreport.1* %{_localedir}/*/LC_MESSAGES/sos.mo diff --git a/src/sosreport b/src/sosreport index 89242fa0..62ceaa10 100755 --- a/src/sosreport +++ b/src/sosreport @@ -49,17 +49,26 @@ def exittermhandler(signum, frame): doExitCode() def doExitCode(): + from threading import enumerate global __breakHits__ __breakHits__ += 1 if ( ( activeCount() > 1 ) and ( __breakHits__ == 1 ) ): print "SIGTERM received, multiple threads detected, waiting for all threads to exit" for thread in enumerate(): - if thread.getName() != "MainThread": - thread.join() - print "All threads ended, cleaning up." + if thread.getName() == "MainThread": + continue + # until we find a way to kill threads in case of > 1 CTRL+C, ignore KeyboardInterrupt + while thread.isAlive(): + try: + thread.join() + except KeyboardInterrupt: + pass + 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" ## 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 ) ): print "Multiple SIGTERMs, single thread, exiting without cleaning up." @@ -74,7 +83,6 @@ signal.signal(signal.SIGTERM, exittermhandler) ## FIXME: Need to figure out how to IPC with child threads in case of ## multiple SIGTERMs. -## FIXME: Need to figure out how to handle SIGKILL - we can't intercept it. # for debugging __raisePlugins__ = 1 @@ -110,13 +118,13 @@ __cmdParser__ = OptionParser_extended(option_class=SosOption) __cmdParser__.add_option("-l", "--list-plugins", action="store_true", \ dest="listPlugins", default=False, \ help="list plugins and available plugin options") -__cmdParser__.add_option("-n", action="extend", \ +__cmdParser__.add_option("-n", "--skip-plugins", action="extend", \ dest="noplugins", type="string", \ help="skip these plugins", default = []) -__cmdParser__.add_option("-e", action="extend", \ +__cmdParser__.add_option("-e", "--enable-plugins", action="extend", \ dest="enableplugins", type="string", \ help="enable these plugins", default = []) -__cmdParser__.add_option("-o", action="extend", \ +__cmdParser__.add_option("-o", "--only-plugins", action="extend", \ dest="onlyplugins", type="string", \ help="enable these plugins only", default = []) __cmdParser__.add_option("-k", action="extend", \ @@ -174,7 +182,10 @@ class progressBar: timeElapsed = round(time() - self.time_start) last_update_relative = round(self.last_amount_update - self.time_start) if timeElapsed >= 10 and self.amount > 0: - percentDone = round(timeElapsed * 100 / self.eta) + try: + percentDone = round(timeElapsed * 100 / self.eta) + except: + percentDone = 0 if percentDone > 100: percentDone = 100 ETA = timeElapsed @@ -182,7 +193,7 @@ class progressBar: ETA = timeElapsed else: ETA = self.eta - ETA = "[%02d:%02d/%02d:%02d]" % (int(timeElapsed/60), timeElapsed % 60, round(ETA/60), ETA % 60) + ETA = "[%02d:%02d/%02d:%02d]" % (int(timeElapsed/60), timeElapsed % 60, int(ETA/60), ETA % 60) else: ETA = "[%02d:%02d/--:--]" % (int(timeElapsed/60), timeElapsed % 60) if self.amount < self.max: @@ -198,9 +209,9 @@ class progressBar: self.progBar = "" for inc in range(0,allFull): if inc == int(allFull / 2): - self.progBar = self.progBar + textcolor("%d%%" % percentDone, "blue") + self.progBar = self.progBar + textcolor("%d%%" % percentDone, "green") elif inc < numHashes: - self.progBar = self.progBar + textcolor('#', "green") + self.progBar = self.progBar + textcolor('#', "gray") else: self.progBar = self.progBar + ' ' self.progBar = " Progress [" + self.progBar + "]" + ETA @@ -262,9 +273,7 @@ class XmlReport: cfile.setNsProp(None, "fname", fname) cchild = cfile.newChild(None, "uid", str(stats[ST_UID])) - cchild.setNsProp(None,"name", getpwuid(stats[ST_UID])[0]) cchild = cfile.newChild(None, "gid", str(stats[ST_GID])) - cchild.setNsProp(None,"name", getpwuid(stats[ST_GID])[0]) cfile.newChild(None, "mode", str(oct(S_IMODE(stats[ST_MODE])))) cchild = cfile.newChild(None, "ctime", strftime('%a %b %d %H:%M:%S %Y', localtime(stats[ST_CTIME]))) cchild.setNsProp(None,"tstamp", str(stats[ST_CTIME])) @@ -322,12 +331,19 @@ def sosreport(): soslog = logging.getLogger('sos') soslog.setLevel(logging.DEBUG) + logging.VERBOSE = logging.INFO - 1 + logging.VERBOSE2 = logging.INFO - 2 + 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 # log to a file flog = logging.FileHandler(logdir + "/sos.log") flog.setFormatter(logging.Formatter('%(asctime)s %(levelname)s: %(message)s')) - flog.setLevel(logging.DEBUG) + flog.setLevel(logging.VERBOSE3) soslog.addHandler(flog) # define a Handler which writes INFO messages or higher to the sys.stderr @@ -340,13 +356,6 @@ def sosreport(): console.setFormatter(logging.Formatter('%(message)s')) soslog.addHandler(console) - logging.VERBOSE = logging.INFO - 1 - logging.VERBOSE2 = logging.INFO - 2 - logging.VERBOSE3 = logging.INFO - 3 - logging.addLevelName(logging.VERBOSE, "verbose") - logging.addLevelName(logging.VERBOSE2,"verbose2") - logging.addLevelName(logging.VERBOSE3,"verbose3") - xmlrep = XmlReport() # set up dict so everyone can share the following @@ -380,7 +389,7 @@ def sosreport(): skippedplugins.append((plugbase, pluginClass(plugbase, commons))) continue if plugbase in __cmdLineOpts__.noplugins: - soslog.log(logging.VERBOSE, _("plug %s skipped (noplugins)") % plugbase) + soslog.log(logging.VERBOSE, _("plug %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: @@ -392,7 +401,7 @@ def sosreport(): 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 --onlyplugin list") % plug) + 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))) @@ -457,11 +466,12 @@ def sosreport(): soslog.error(_("no valid plugins found")) sys.exit(1) + # FIXME: make -l output more concise if len(loadedplugins): print _("The following plugins are currently enabled:") print for (plugname,plug) in loadedplugins: - print " %-25s %s" % (textcolor(plugname,"lblue"),plug.get_description()) + print " %-25s %s" % (textcolor(plugname,"lblue"),plug.get_description()) else: print _("No plugin enabled.") print @@ -470,7 +480,7 @@ def sosreport(): print _("The following plugins are currently disabled:") print for (plugname,plugclass) in skippedplugins: - print " %-25s %s" % (textcolor(plugname,"lgray"),plugclass.get_description()) + print " %-25s %s" % (textcolor(plugname,"cyan"),plugclass.get_description()) print if len(alloptions): @@ -515,9 +525,10 @@ def sosreport(): try: raw_input(_("""This utility will collect some detailed information about the hardware and setup of your Red Hat Enterprise Linux system. -This information will be used to diagnose problems with your -system and will be considered confidential information. -Red Hat will use this information for diagnostic purposes ONLY. +The information is collected and an archive is packaged under +/tmp, which you can send to a support rappresentative. +Red Hat will use this information for diagnostic purposes ONLY +and it will be considered confidential information. This process may take a while to complete. No changes will be made to your system. @@ -528,6 +539,8 @@ Press ENTER to continue, or CTRL-C to quit. print sys.exit(0) + policy.preWork() + # Call the diagnose() method for each plugin tmpcount = 0 for plugname, plug in loadedplugins: @@ -542,21 +555,26 @@ Press ENTER to continue, or CTRL-C to quit. print _("One or more plugins have detected a problem in your configuration.") print _("Please review the following messages:") print + + fp = open(rptdir + "/diagnose.txt", "w") for plugname, plug in loadedplugins: - for tmpcount2 in range(0,len(plug.diagnose_msgs)): - if tmpcount2 == 0: - soslog.warning( textcolor("%s:" % plugname, "red") ) - soslog.warning(" * %s" % plug.diagnose_msgs[tmpcount2]) + for tmpcount2 in range(0,len(plug.diagnose_msgs)): + if tmpcount2 == 0: + soslog.warning( textcolor("%s:" % plugname, "red") ) + soslog.warning(" * %s" % plug.diagnose_msgs[tmpcount2]) + fp.write("%s: %s\n" % (plugname, plug.diagnose_msgs[tmpcount2]) ) + 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": - del yorno + yorno = raw_input( _("Are you sure you would like to continue (y/n) ? ") ) + if yorno == _("y") or yorno == _("Y"): print break - else: + elif yorno == _("n") or yorno == _("N"): sys.exit(0) + del yorno except KeyboardInterrupt: print sys.exit(0) @@ -604,18 +622,22 @@ Press ENTER to continue, or CTRL-C to quit. plugname, plug = loadedplugins.pop(0) if not plug.wait(0.5): finishedplugins.append((plugname,plug)) - soslog.log(logging.VERBOSE2, "plugin %s has returned" % plugname) + soslog.log(logging.DEBUG, "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) + soslog.log(logging.DEBUG, "plugin %s still hasn't returned" % plugname) loadedplugins.append((plugname,plug)) if __cmdLineOpts__.progressbar: pbar.update() loadedplugins = finishedplugins del finishedplugins - xmlrep.serialize_to_file(rptdir + "/" + "sosreport.xml") + for plugname, plug in loadedplugins: + for oneFile in plug.copiedFiles: + xmlrep.add_file(oneFile["srcpath"], os.stat(oneFile["srcpath"])) + + xmlrep.serialize_to_file(rptdir + "/sosreport.xml") # Call the analyze method for each plugin for plugname, plug in loadedplugins: @@ -680,8 +702,13 @@ Press ENTER to continue, or CTRL-C to quit. # Call the report method for each plugin for plugname, plug in loadedplugins: - html = plug.report() - rfd.write(html) + try: + html = plug.report() + except: + if __raisePlugins__: + raise + else: + rfd.write(html) rfd.write("") diff --git a/src/sosreport.1 b/src/sosreport.1 index cf76afdb..95f427b5 100644 --- a/src/sosreport.1 +++ b/src/sosreport.1 @@ -3,10 +3,10 @@ sosreport \- Generate debugging information for this system .SH SYNOPSIS .B sosreport -[-a|--alloptions] [-f|--fastoptions] [-g|--gatheronly] - [-l|--list-plugins] [-n|--noplugin \fIplugin-name\fR] - [-o|--onlyplugin \fIplugin-name\fR] - [-v|--verbose [...]] [-m|--multithreaded] + [-l|--list-plugins]\fR + [-n|--skip-plugins plugin-names] [-e|--enable-plugins plugin-names] [-o|--only-plugins plugin-names]\fR + [-a|--alloptions] [-v|--verbose] + [--no-multithread] [--no-progressbar] .SH DESCRIPTION \fBsosreport\fR generates a compressed tarball of debugging information for the system it is run on that can be sent to technical support @@ -14,38 +14,38 @@ reps that will give them a more complete view of the overall system status. .SH OPTIONS .TP -.B \-a, \--alloptions -Enable all options for all loaded plugins +.B \-l, \--list-plugins +This will list all available plugins showing which ones will be enabled by the current configuration. It will also show all plugin options which can be +modified using the -k option (see below). .TP -.B \-f, \--fastoptions -Enable all options marked as "fast" for loaded plugins. This will -reduce running time while still gathering helpful information, but -you may be asked to re-run later with some or all "slow" options -enabled depending on the specific issue. +.B \-n, --skip-plugins PLUGNAME[,PLUGNAME] +Do not load specified plugin(s). To specify multiple plugins, separate them with a comma. .TP -.B \-g, \--gatheronly -Gather the diagnostic data and bundle it up, but do not attempt to -send it to any support site. This option currently has no effect as -sosreport currently does not support report transmission. +.B \-e, --enable-plugins PLUGNAME[,PLUGNAME] +Enable the specified plugin(s). To specify multiple plugins, separate them with a comma. .TP -.B \-l, \--list-plugins -List available plugins +.B \-o, --only-plugins PLUGNAME[,PLUGNAME] +Enable the specified plugin(s) only (all other plugins should be disabled). To specify multiple plugins, separate them with a comma. .TP -.B \-n, \--noplugin -Do not load specified plugin(s) +.B \-k PLUGNAME.PLUGOPT[=VALUE] +This is used to specify options for plugins. A list of available plugin options can be obtained from the output of --list-plugins. +If no value is specified and the option is a boolean (on/off), it will be set to "on". .TP -.B \-o, \--onlyplugin -Load only the specified plugin(s), all otherplugins should be disabled +.B \-a, \--alloptions +Enable all (boolean) options for all loaded plugins. .TP .B \-v, \--verbose -Increase the verbosity of the output as sosreport is running. This option -can be specified more than once. -.TP -.B \-m, \--multithreaded -Enable a multithreaded collection and analysis of the sosreport data. Please -note that this option is experimental and is known to have intermittent issues. -.SH BUGS -The multithreaded option can fail intermittently, please use it with care. +Increase the verbosity of the output as sosreport is running. Multiple -v mean more verbosity. +.TP +.B \--no-progressbar +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 +.nf +Navid Sheikhol-Eslami +.fi .SH AUTHORS .nf Steve Conklin -- cgit