aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorshnavid <shnavid@ef72aa8b-4018-0410-8976-d6e080ef94d8>2007-07-12 07:29:36 +0000
committershnavid <shnavid@ef72aa8b-4018-0410-8976-d6e080ef94d8>2007-07-12 07:29:36 +0000
commit9af40ceda54d5979730d95999359da33191839fe (patch)
treee09e2ee395d84ba973ae049ef7a4a3e2b7fbebd5
parentc96eab04123db867ca2ef23f51dccea46e8b9801 (diff)
downloadsos-9af40ceda54d5979730d95999359da33191839fe.tar.gz
* bumped version to 1.7r1.7
* curses menu disabled by default (enable with -c) * sosreport output friendlier to the user (and similar to sysreport) * smarter plugin listing which also shows options and disable/enabled plugins * require root permissions only for actual sosreport generation * fix in -k where option value was treated as string instead of int * made progressbar wider (60 chars) * selinux plugin is enabled only if selinux is also enabled on the system * made some errors less verbose to the user * made sosreport not copy files pointed by symbolic links (same as sysreport, we don't need /usr/bin/X or /sbin/ifup) * copy links as links (cp -P) * added plugin get_description() that returns a short decription for the plugin * guess sosreport name from system's name git-svn-id: svn+ssh://svn.fedorahosted.org/svn/sos/trunk@195 ef72aa8b-4018-0410-8976-d6e080ef94d8
-rw-r--r--src/TODO2
-rw-r--r--src/lib/sos/plugins/selinux.py9
-rw-r--r--src/lib/sos/plugintools.py35
-rwxr-xr-xsrc/lib/sos/policyredhat.py23
-rw-r--r--src/setup.py2
-rw-r--r--src/sos.spec4
-rwxr-xr-xsrc/sosreport166
7 files changed, 134 insertions, 107 deletions
diff --git a/src/TODO b/src/TODO
index ac78e960..448aa33f 100644
--- a/src/TODO
+++ b/src/TODO
@@ -5,6 +5,8 @@ To Do List:
* 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
diff --git a/src/lib/sos/plugins/selinux.py b/src/lib/sos/plugins/selinux.py
index 2e56964a..925c2ad7 100644
--- a/src/lib/sos/plugins/selinux.py
+++ b/src/lib/sos/plugins/selinux.py
@@ -13,6 +13,7 @@
## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
import sos.plugintools
+import commands
class selinux(sos.plugintools.PluginBase):
"""This plugin gathers selinux related information
@@ -25,3 +26,11 @@ class selinux(sos.plugintools.PluginBase):
self.collectExtOutput("/bin/rpm -q -V selinux-policy-strict")
return
+ def checkenabled(self):
+ # is selinux enabled ?
+ try:
+ if commands.getoutput("/usr/sbin/sestatus").split(":")[1].strip() == "disabled":
+ return False
+ except:
+ pass
+ return True
diff --git a/src/lib/sos/plugintools.py b/src/lib/sos/plugintools.py
index 3d80df44..15fccfdf 100644
--- a/src/lib/sos/plugintools.py
+++ b/src/lib/sos/plugintools.py
@@ -85,7 +85,7 @@ class PluginBase:
except KeyboardInterrupt:
raise KeyboardInterrupt
except Exception, e:
- self.cInfo['soslog'].error("Problem at path %s (%s)\n" % (abspath,e))
+ self.cInfo['soslog'].warning("Problem at path %s (%s)\n" % (abspath,e))
break
return False
@@ -141,7 +141,7 @@ class PluginBase:
except KeyboardInterrupt:
raise KeyboardInterrupt
except Exception, e:
- self.cInfo['soslog'].error("Problem at path %s (%s)" % (srcpath+'/'+afile, e))
+ self.cInfo['soslog'].warning("Problem at path %s (%s)" % (srcpath+'/'+afile, e))
# if on forbidden list, abspath is null
if not abspath == '':
dstslname = sosRelPath(self.cInfo['rptdir'], abspath)
@@ -156,22 +156,8 @@ class PluginBase:
except KeyboardInterrupt:
raise KeyboardInterrupt
except Exception, e:
- self.cInfo['soslog'].error("Problem at path %s (%s)" % (srcpath, e))
+ self.cInfo['soslog'].debug("Problem at path %s (%s)" % (srcpath, e))
-
- # Recurse to copy whatever it points to
- newpath = os.path.normpath(os.path.join(os.path.dirname(srcpath), link))
- try:
- self.doCopyFileOrDir(newpath)
- except SystemExit:
- raise SystemExit
- except KeyboardInterrupt:
- raise KeyboardInterrupt
- except EnvironmentError, (errno, strerror):
- if (errno != 17):
- # we ignore 'file exists' errors
- self.cInfo['soslog'].error("Problem at path %s ([%d] %s)" % (newpath, errno, strerror))
-
return abspath
else:
@@ -195,7 +181,7 @@ class PluginBase:
"""
try:
# pylint: disable-msg = W0612
- status, shout, sherr, runtime = sosGetCommandOutput("/bin/cp --parents -p " + src +" " + self.cInfo['dstroot'])
+ status, shout, sherr, 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)
@@ -272,10 +258,9 @@ class PluginBase:
""" Execute a command independantly of the output gathering part of
sosreport
"""
- # First check to make sure the binary exists and is runnable.
+ # Log if binary is not runnable or does not exist
if not os.access(prog.split()[0], os.X_OK):
- self.cInfo['soslog'].log(logging.VERBOSE2, "Binary '%s' does not exist or is not runnable" % prog.split()[0])
- return
+ 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)
@@ -333,6 +318,7 @@ class PluginBase:
outfd.close()
if root_symlink:
+ # 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:
@@ -422,6 +408,13 @@ class PluginBase:
except:
self.cInfo['soslog'].log(logging.VERBOSE, "Error collecting output of '%s'" % prog,)
+ def get_description(self):
+ """ This function will return the description for the plugin"""
+ try:
+ return self.__doc__.strip()
+ except:
+ return "<no description available>"
+
def checkenabled(self):
""" This function can be overidden to let the plugin decide whether
it should run or not.
diff --git a/src/lib/sos/policyredhat.py b/src/lib/sos/policyredhat.py
index 80643576..34177347 100755
--- a/src/lib/sos/policyredhat.py
+++ b/src/lib/sos/policyredhat.py
@@ -18,6 +18,7 @@
## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
import os
+import commands
import sys
import string
from tempfile import gettempdir
@@ -75,16 +76,11 @@ class SosPolicy:
return (name, version, release, arch)
def packageResults(self):
- print "Packaging results to send to support..."
+ localname = commands.getoutput("/bin/uname -n").split(".")[0]
+ name = raw_input("Please enter your first initial and last name [%s]: " % localname)
+ if len(name) == 0: name = localname
- name=""
- while len(name)==0:
- print "Please enter your first initial and last name (jsmith): ",
- name = sys.stdin.readline()[:-1]
-
- print "Please enter the case number that you are generating this",
- print "report for: ",
- ticketNumber = sys.stdin.readline()[:-1]
+ ticketNumber = raw_input("Please enter the case number that you are generating this report for: ")
if len(ticketNumber):
namestr = name + "." + ticketNumber
@@ -92,7 +88,7 @@ class SosPolicy:
namestr = name
ourtempdir = gettempdir()
- tarballName = os.path.join(ourtempdir, namestr + ".tar.bz2")
+ tarballName = os.path.join(ourtempdir, "sosreport-" + namestr + ".tar.bz2")
namestr = namestr + "-" + str(random.randint(1, 999999))
@@ -100,12 +96,13 @@ class SosPolicy:
tarcmd = "/bin/tar -jcf %s %s" % (tarballName, namestr)
+ print
print "Creating compressed tar archive..."
if not os.access(string.split(tarcmd)[0], os.X_OK):
print "Unable to create tarball"
return
- # gotta be a better way...
+ # FIXME: gotta be a better way...
os.system("/bin/mv %s %s" % (self.cInfo['dstroot'], aliasdir))
curwd = os.getcwd()
os.chdir(ourtempdir)
@@ -117,7 +114,9 @@ class SosPolicy:
os.system("/bin/mv %s %s" % (aliasdir, self.cInfo['dstroot']))
sys.stdout.write("\n")
- print "Your sosreport has been generated and saved in %s" % tarballName
+ print "Your sosreport has been generated and saved in %s" % tarballName
+ print "Please send this file to your support representative."
sys.stdout.write("\n")
+
return
diff --git a/src/setup.py b/src/setup.py
index b6030227..23e9a4f4 100644
--- a/src/setup.py
+++ b/src/setup.py
@@ -9,7 +9,7 @@ import sys,os,time
# change version in spec file along with this string
setup(
name = 'sos',
- version = '1.6',
+ version = '1.7',
license = 'GPL',
description = 'System Support Tools',
long_description = """Sos is a set of tools that gathers information about system
diff --git a/src/sos.spec b/src/sos.spec
index 24e0dced..dd1755ca 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.6
-%define release 5
+%define version 1.7
+%define release 0
Summary: A set of tools to gather troubleshooting information from a system
Name: %{name}
diff --git a/src/sosreport b/src/sosreport
index 34f6172f..ae8d6609 100755
--- a/src/sosreport
+++ b/src/sosreport
@@ -39,6 +39,8 @@ from stat import *
from time import strftime, localtime
from pwd import getpwuid
+__version__ = 1.7
+
__breakHits__ = 0 # Use this to track how many times we enter the exit routine
## Set up routines to be linked to signals for termination handling
@@ -106,13 +108,13 @@ __cmdParser__.add_option("-l", "--list-plugins", action="store_true", \
help="list existing plugins")
__cmdParser__.add_option("-n", "--noplugin", action="extend", \
dest="noplugins", type="string", \
- help="list of plugins _not_ to load")
+ help="list of plugins _not_ to load", default = [])
__cmdParser__.add_option("-o", "--onlyplugin", action="extend", \
dest="onlyplugins", type="string", \
- help="list of plugins to load")
+ help="list of plugins to load", default = [])
__cmdParser__.add_option("-e", "--enableplugin", action="extend", \
dest="enableplugins", type="string", \
- help="list of plugins to enable")
+ help="list of plugins to enable", default = [])
__cmdParser__.add_option("-k", "--pluginopts", action="extend", \
dest="plugopts", type="string", \
help="plugin options in plugin_name.option=value format")
@@ -122,6 +124,9 @@ __cmdParser__.add_option("-v", "--verbose", action="count", \
__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", \
+ dest="use_curses", default=False, \
+ help="Do not display a progress bar.")
__cmdParser__.add_option("-m", "--multithreaded", action="store_true", \
dest="multithread", \
help="Use the multithreaded information gathering mode to speed up the report (experimental)")
@@ -304,6 +309,7 @@ def sosreport():
This is the top-level function that gathers and processes all sosreport information
"""
loadedplugins = []
+ skippedplugins = []
alloptions = []
# perhaps we should automatically locate the policy module??
@@ -363,121 +369,139 @@ def sosreport():
# Make policy aware of the commons
policy.setCommons(commons)
+
+ sys.stdout.write("\n")
+ soslog.info("sosreport (version %s)" % (__version__) )
+ sys.stdout.write("\n")
- # print list of available plugins
+ # generate list of available plugins
plugins = os.listdir(pluginpath)
- if __cmdLineOpts__.listPlugins:
- print "Available plugins:"
- print
- for plug in plugins:
- try:
- if ((plug[-3:] == '.py') and (plug != "__init__.py")):
- plugbase = plug[:-3]
- if policy.validatePlugin(pluginpath + plug):
- pluginClass = importPlugin("sos.plugins." + plugbase, plugbase)
- else:
- soslog.warning("plugin %s does not validate, skipping" % plug)
- continue
- if not pluginClass(plugbase, commons).checkenabled():
- print "* %s (inactive)" % plugbase
- continue
- if not pluginClass(plugbase, commons).defaultenabled():
- print "* %s (disabled by default)" % plugbase
- continue
- print " " + plugbase
- except:
- print "ouch"
- print
- sys.exit()
-
- # to go anywhere further than listing the plugins we will need root permissions.
- #
- if os.getuid() != 0:
- print 'You must run sosreport as root!'
- sys.exit(1)
+ plugins.sort()
# validate and load plugins
for plug in plugins:
plugbase = plug[:-3]
if not plug[-3:] == '.py' or plugbase == "__init__":
continue
- if __cmdLineOpts__.noplugins and plugbase not in __cmdLineOpts__.noplugins:
- soslog.log(logging.VERBOSE, "plug %s skipped" % plugbase)
- continue
- if __cmdLineOpts__.onlyplugins and not plugbase in __cmdLineOpts__.onlyplugins:
- soslog.log(logging.VERBOSE, "plug %s skipped" % plugbase)
- continue
try:
#print "importing plugin: %s" % plugbase
try:
if policy.validatePlugin(pluginpath + plug):
pluginClass = importPlugin("sos.plugins." + plugbase, plugbase)
else:
- soslog.warning("Plugin %s does not validate, skipping" % plug)
+ soslog.warning("plugin %s does not validate, skipping" % plug)
+ skippedplugins.append((plugbase, pluginClass(plugbase, commons)))
+ continue
+ if plugbase in __cmdLineOpts__.noplugins:
+ soslog.log(logging.VERBOSE, "plug %s skipped (noplugins)" % plugbase)
+ skippedplugins.append((plugbase, pluginClass(plugbase, commons)))
continue
- if not __cmdLineOpts__.onlyplugins and not pluginClass(plugbase, commons).defaultenabled():
- if __cmdLineOpts__.enableplugins and plugbase in __cmdLineOpts__.enableplugins:
- soslog.log(logging.VERBOSE, "plugin %s manually activated" % plugbase)
- else:
- soslog.log(logging.VERBOSE, "Plugin %s not loaded by default." % plug)
- continue
- if not pluginClass(plugbase, commons).checkenabled():
- soslog.log(logging.VERBOSE, "Plugin %s is inactive." % plug)
+ if not pluginClass(plugbase, commons).checkenabled() and not plugbase in __cmdLineOpts__.enableplugins and not plugbase in __cmdLineOpts__.onlyplugins:
+ soslog.log(logging.VERBOSE, "plugin %s is inactive (use -e or -o to enable)." % plug)
+ skippedplugins.append((plugbase, pluginClass(plugbase, commons)))
+ continue
+ if not pluginClass(plugbase, commons).defaultenabled() and not plugbase in __cmdLineOpts__.enableplugins and not plugbase in __cmdLineOpts__.onlyplugins:
+ soslog.log(logging.VERBOSE, "plugin %s not loaded by default (use -e or -o to enable)." % plug)
+ skippedplugins.append((plugbase, pluginClass(plugbase, commons)))
+ continue
+ if __cmdLineOpts__.onlyplugins and not plugbase in __cmdLineOpts__.onlyplugins:
+ soslog.log(logging.VERBOSE, "plugin %s not specified in --onlyplugin list" % plug)
+ skippedplugins.append((plugbase, pluginClass(plugbase, commons)))
continue
loadedplugins.append((plugbase, pluginClass(plugbase, commons)))
except:
soslog.warning("Plugin %s does not install, skipping" % plug)
raise
except:
+ soslog.warning("plugin load failed for %s" % plug)
if __raisePlugins__:
raise
- soslog.warning("plugin load failed for %s" % plug)
+
+ # First, gather and process options
+ for plugname, plug in loadedplugins:
+ soslog.log(logging.VERBOSE3, "processing options from plugin: %s" % plugname)
+ names, parms = plug.getAllOptions()
+ for optname, optparm in zip(names, parms):
+ alloptions.append((plug, plugname, optname, optparm))
+
+ if __cmdLineOpts__.listPlugins:
+ if not len(loadedplugins) and not len(skippedplugins):
+ soslog.error("no valid plugins found")
+ sys.exit(1)
+
+ print "The following plugins are currently enabled:"
+ print
+ for (plugname,plug) in loadedplugins:
+ print " %-15s %s" % (plugname,plug.get_description())
+
+ print
+ print "The following plugin options are available:"
+ print
+ for (plug, plugname, optname, optparm) in alloptions:
+ print " %-15s %s [%d]" % (plugname + "." + optname, optparm["desc"], optparm["enabled"])
+
+ print
+ print "The following plugins are currently disabled:"
+ print
+ for (plugname,plugclass) in skippedplugins:
+ print " %-15s %s" % (plugname,plugclass.get_description())
+
+ print
+ sys.exit()
+
+ # to go anywhere further than listing the plugins we will need root permissions.
+ #
+ if os.getuid() != 0:
+ print 'sosreport requires root permissions to run.'
+ sys.exit(1)
+
+ # we don't need to keep in memory plugins we are not going to use
+ del skippedplugins
if not len(loadedplugins):
soslog.error("no valid plugins were enabled")
sys.exit(1)
- sys.stdout.write("\n")
- soslog.info("Welcome to sosreport (%d plugins loaded)" % (len(loadedplugins)))
- sys.stdout.write("\n")
+ 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.
- # Iterate over plugins for each stage
+This process may take a while to complete.
+No changes will be made to your system.
- # First, gather and process options
- for plugname, plug in loadedplugins:
- soslog.log(logging.VERBOSE3, "processing options from plugin: %s" % plugname)
- try:
- len(__cmdLineOpts__.noplugins)
- if plugname not in __cmdLineOpts__.noplugins:
- names, parms = plug.getAllOptions()
- for optname, optparm in zip(names, parms):
- alloptions.append((plug, plugname, optname, optparm))
- except:
- names, parms = plug.getAllOptions()
- for optname, optparm in zip(names, parms):
- alloptions.append((plug, plugname, optname, optparm))
+Press ENTER to continue, or CTRL-C to quit.
+""")
+ except KeyboardInterrupt:
+ print
+ sys.exit(0)
+ # Iterate over plugins for each stage
if __cmdLineOpts__.plugopts:
opts = {}
for opt in __cmdLineOpts__.plugopts:
try: opt, val = opt.split("=")
except: val=1
plug, opt = opt.split(".")
+ try: val = int(val) # try to convert string "val" to int()
+ except: pass
try: opts[plug]
except KeyError: opts[plug] = []
opts[plug].append( (opt,val) )
for plugname, plug in loadedplugins:
if opts.has_key(plugname):
for opt,val in opts[plugname]:
+ soslog.log(logging.VERBOSE, "setting option %s for plugin %s to %s" % (plugname,opt,val))
plug.setOption(opt,val)
+ del opt,opts,val
elif not __cmdLineOpts__.fastoptions and not __cmdLineOpts__.usealloptions:
- if len(alloptions):
+ if len(alloptions) and __cmdLineOpts__.use_curses:
try:
get_curse_options(alloptions)
except "Cancelled":
sys.exit("Exiting.")
- else:
- soslog.info("no options available for selected plugins")
elif __cmdLineOpts__.fastoptions:
for i in range(len(alloptions)):
for plug, plugname, optname, optparm in alloptions:
@@ -492,7 +516,7 @@ def sosreport():
# Setup the progress bar
if __cmdLineOpts__.progressbar:
- pbar = progressBar(0, len(loadedplugins) * 33, 40)
+ pbar = progressBar(0, len(loadedplugins) * 33, totalWidth = 60)
# Call the setup method for each plugin
for plugname, plug in loadedplugins:
@@ -613,7 +637,7 @@ def sosreport():
# package up the results for the support organization
policy.packageResults()
# delete gathered files
- os.system("rm -rf %s" % dstroot)
+ os.system("/bin/rm -rf %s" % dstroot)
# automated submission will go here
# Close all log files and perform any cleanup