aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
authorastokes <astokes@ef72aa8b-4018-0410-8976-d6e080ef94d8>2008-10-01 13:17:46 +0000
committerastokes <astokes@ef72aa8b-4018-0410-8976-d6e080ef94d8>2008-10-01 13:17:46 +0000
commit6f1e13198edb22c3d47d4c151dbe1d4b7e0fc4c6 (patch)
tree4ab072b6412797d4e65bc3594e01fd877d88914e /src/lib
parent46071f546f4718d80e2c54c938f774ed40a171c7 (diff)
downloadsos-6f1e13198edb22c3d47d4c151dbe1d4b7e0fc4c6.tar.gz
RHEL-5 branch update
git-svn-id: svn+ssh://svn.fedorahosted.org/svn/sos/trunk@524 ef72aa8b-4018-0410-8976-d6e080ef94d8
Diffstat (limited to 'src/lib')
-rwxr-xr-xsrc/lib/sos/helpers.py123
-rw-r--r--src/lib/sos/plugins/apache.py1
-rw-r--r--src/lib/sos/plugins/autofs.py36
-rw-r--r--src/lib/sos/plugins/cluster.py351
-rw-r--r--src/lib/sos/plugins/devicemapper.py18
-rw-r--r--src/lib/sos/plugins/emc.py28
-rw-r--r--src/lib/sos/plugins/filesys.py7
-rw-r--r--src/lib/sos/plugins/general.py20
-rw-r--r--src/lib/sos/plugins/hardware.py17
-rw-r--r--src/lib/sos/plugins/initrd.py4
-rw-r--r--src/lib/sos/plugins/kernel.py57
-rw-r--r--src/lib/sos/plugins/ldap.py25
-rw-r--r--src/lib/sos/plugins/named.py25
-rw-r--r--src/lib/sos/plugins/networking.py14
-rw-r--r--src/lib/sos/plugins/nfsserver.py5
-rw-r--r--src/lib/sos/plugins/pam.py2
-rw-r--r--src/lib/sos/plugins/process.py3
-rw-r--r--src/lib/sos/plugins/rpm.py14
-rw-r--r--src/lib/sos/plugins/selinux.py24
-rw-r--r--src/lib/sos/plugins/squid.py7
-rw-r--r--src/lib/sos/plugins/startup.py1
-rw-r--r--src/lib/sos/plugins/systemtap.py10
-rw-r--r--src/lib/sos/plugins/x11.py13
-rw-r--r--src/lib/sos/plugins/xen.py20
-rw-r--r--src/lib/sos/plugins/yum.py21
-rw-r--r--src/lib/sos/plugintools.py323
-rwxr-xr-xsrc/lib/sos/policyredhat.py329
27 files changed, 626 insertions, 872 deletions
diff --git a/src/lib/sos/helpers.py b/src/lib/sos/helpers.py
index 77f85b01..bcdee6fb 100755
--- a/src/lib/sos/helpers.py
+++ b/src/lib/sos/helpers.py
@@ -25,29 +25,9 @@
"""
helper functions used by sosreport and plugins
"""
-import os, popen2, fcntl, select, sys, commands, signal
-from time import time, sleep
-
-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
+import os, popen2, fcntl, select, itertools, sys, commands
+from time import time
+from tempfile import mkdtemp
def importPlugin(pluginname, name):
""" Import a plugin to extend capabilities of sosreport
@@ -77,72 +57,17 @@ def makeNonBlocking(afd):
fcntl.fcntl(afd, fcntl.F_SETFL, fl | os.FNDELAY)
-def sosGetCommandOutput(command, timeout = 300):
+def sosGetCommandOutput(command):
""" Execute a command and gather stdin, stdout, and return status.
"""
- soslog = logging.getLogger('sos')
-
- # Log if binary is not runnable or does not exist
- for path in os.environ["PATH"].split(":"):
- cmdfile = command.strip("(").split()[0]
- # handle both absolute or relative paths
- if ( ( not os.path.isabs(cmdfile) and os.access(os.path.join(path,cmdfile), os.X_OK) ) or \
- ( os.path.isabs(cmdfile) and os.access(cmdfile, os.X_OK) ) ):
- break
- else:
- soslog.log(logging.VERBOSE, "binary '%s' does not exist or is not runnable" % cmdfile)
- return (127, "", 0)
-
- # these are file descriptors, not file objects
- r, w = os.pipe()
-
- pid = os.fork()
-
- if pid:
- # we are the parent
- os.close(w) # use os.close() to close a file descriptor
- 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([r], [], [], 1)
- if r in ready[0]:
- txt = txt + r_fd.read()
- # is child still running ?
- try: os.waitpid(pid, os.WNOHANG)
- except:
- # not running, make sure the child process gets cleaned up
- try: sts = os.waitpid(pid, 0)[1]
- except: pass
- break
- # 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) )
- try: os.kill(pid, signal.SIGKILL)
- except: pass
- break
- if txt[-1:] == '\n': txt = txt[:-1]
- return (sts, txt, time()-stime)
- else:
- # we are the child
- os.dup2(r, 0)
- os.dup2(w, 1)
- os.dup2(w, 2)
-
- 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):
- try: os.close(fd)
- except OSError: pass
- os.execl("/bin/sh", "/bin/sh", "-c", command)
- os._exit(127)
+ stime = time()
+ 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
@@ -167,11 +92,23 @@ def allEqual(elements):
return False
return True
-def commonPrefix(l1, l2, common = []):
+
+def commonPrefix(*sequences):
''' 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 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]])
+ # 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 ]
def sosRelPath(path1, path2, sep=os.path.sep, pardir=os.path.pardir):
''' return a relative path from path1 equivalent to path path2.
@@ -187,9 +124,3 @@ def sosRelPath(path1, path2, sep=os.path.sep, pardir=os.path.pardir):
return path2 # leave path absolute if nothing at all in common
return sep.join( [pardir]*len(u1) + u2 )
-def sosReadFile(fname):
- ''' reads a file and returns its contents'''
- fp = open(fname,"r")
- content = fp.read()
- fp.close()
- return content
diff --git a/src/lib/sos/plugins/apache.py b/src/lib/sos/plugins/apache.py
index 10061918..c5250fd9 100644
--- a/src/lib/sos/plugins/apache.py
+++ b/src/lib/sos/plugins/apache.py
@@ -13,6 +13,7 @@
## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
import sos.plugintools
+from threading import Thread
class apache(sos.plugintools.PluginBase):
"""Apache related information
diff --git a/src/lib/sos/plugins/autofs.py b/src/lib/sos/plugins/autofs.py
index 16a8d3fb..48dd57b4 100644
--- a/src/lib/sos/plugins/autofs.py
+++ b/src/lib/sos/plugins/autofs.py
@@ -15,7 +15,7 @@
## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
import sos.plugintools
-import os
+import os, re
class autofs(sos.plugintools.PluginBase):
"""autofs server-related information
@@ -24,8 +24,38 @@ class autofs(sos.plugintools.PluginBase):
if self.cInfo["policy"].runlevelDefault() in self.cInfo["policy"].runlevelByService("autofs"):
return True
return False
-
+
+ def checkdebug(self):
+ """ testing if autofs debug has been enabled anywhere
+ """
+ # Global debugging
+ optlist=[]
+ opt = self.fileGrep(r"^(DEFAULT_LOGGING|DAEMONOPTIONS)=(.*)", "/etc/sysconfig/autofs")
+ for opt1 in opt:
+ for opt2 in opt1.split(" "):
+ optlist.append(opt2)
+ for dtest in optlist:
+ if dtest == "--debug" or dtest == "debug":
+ return True
+
+ def getdaemondebug(self):
+ """ capture daemon debug output
+ """
+ debugout = self.fileGrep(r"^(daemon.*)\s+(\/var\/log\/.*)", "/etc/sysconfig/autofs")
+ for i in debugout:
+ return i[1]
+
def setup(self):
self.addCopySpec("/etc/auto*")
self.addCopySpec("/etc/sysconfig/autofs")
- self.addCopySpec("/etc/rc.d/init.d/autofs")
+ self.addCopySpec("/etc/init.d/autofs")
+ self.collectExtOutput("/bin/rpm -qV autofs")
+ self.collectExtOutput("/etc/init.d/autofs status")
+ self.collectExtOutput("ps auxwww | grep automount")
+ self.collectExtOutput("/bin/egrep -e 'automount|pid.*nfs' /proc/mounts")
+ self.collectExtOutput("/bin/mount | egrep -e 'automount|pid.*nfs'")
+ self.collectExtOutput("/sbin/chkconfig --list autofs")
+ if self.checkdebug():
+ self.addCopySpec(self.getdaemondebug())
+ return
+
diff --git a/src/lib/sos/plugins/cluster.py b/src/lib/sos/plugins/cluster.py
index 6d4de2a0..f6169ddb 100644
--- a/src/lib/sos/plugins/cluster.py
+++ b/src/lib/sos/plugins/cluster.py
@@ -25,178 +25,139 @@ class cluster(sos.plugintools.PluginBase):
('taskdump', 'trigger 3 sysrq+t dumps every 5 seconds (dangerous)', 'slow', False)]
def checkenabled(self):
- rhelver = self.cInfo["policy"].rhelVersion()
- if rhelver == 4:
- self.packages = [ "ccs", "cman", "cman-kernel", "magma", "magma-plugins",
- "rgmanager", "fence", "dlm", "dlm-kernel", "gulm",
- "GFS", "GFS-kernel", "lvm2-cluster" ]
- elif rhelver == 5:
- self.packages = [ "rgmanager", "luci", "ricci", "system-config-cluster",
- "gfs-utils", "gnbd", "kmod-gfs", "kmod-gnbd", "lvm2-cluster" ]
-
- self.files = [ "/etc/cluster/cluster.conf", "/proc/cluster" ]
- return sos.plugintools.PluginBase.checkenabled(self)
+ # enable if any related package is installed
+ for pkg in [ "rgmanager", "luci", "ricci", "system-config-cluster",
+ "gfs-utils", "gnbd", "kmod-gfs", "kmod-gnbd", "lvm2-cluster" ]:
+ if self.cInfo["policy"].pkgByName(pkg) != None:
+ return True
+
+ # enable if any related file is present
+ for fname in [ "/etc/cluster/cluster.conf", "/proc/cluster" ]:
+ try: os.stat(fname)
+ except:pass
+ else: return True
+
+ # no data related to RHCS/GFS exists
+ return False
def has_gfs(self):
- try:
- if len(self.doRegexFindAll(r'^\S+\s+\S+\s+gfs\s+.*$', "/etc/mtab")):
- return True
- except:
- return False
+ fp = open("/proc/mounts","r")
+ for line in fp.readlines():
+ mntline = line.split(" ")
+ if mntline[2] == "gfs":
+ return True
+ fp.close()
+ return False
def diagnose(self):
- rhelver = self.cInfo["policy"].rhelVersion()
-
- # check if the minimum set of packages is installed
- # for RHEL4 RHCS(ccs, cman, cman-kernel, magma, magma-plugins, (dlm, dlm-kernel) || gulm, perl-Net-Telnet, rgmanager, fence)
- # RHEL4 GFS (GFS, GFS-kernel, ccs, lvm2-cluster, fence)
-
- pkgs_check = []
- mods_check = []
- serv_check = []
-
- if rhelver == 4:
- pkgs_check.extend( [ "ccs", "cman", "magma", "magma-plugins", "perl-Net-Telnet", "rgmanager", "fence" ] )
- mods_check.extend( [ "cman", "dlm" ] )
- if self.has_gfs():
- mods_check.append("gfs")
- serv_check.extend( [ "cman", "ccsd", "rgmanager", "fenced" ] )
- if self.has_gfs():
- serv_check.extend( ["gfs", "clvmd"] )
- elif rhelver == 5:
- pkgs_check.extend ( [ "cman", "perl-Net-Telnet", "rgmanager" ] )
- mods_check.extend( [ "dlm" ] )
- if self.has_gfs():
- mods_check.extend( ["gfs", "gfs2"] )
- serv_check.extend( [ "cman", "rgmanager" ] )
- if self.has_gfs():
- serv_check.extend( ["gfs", "clvmd"] )
-
- # check that kernel module packages are installed for
- # running kernel version
-
- for modname in mods_check:
- found = 0
-
- if self.cInfo["policy"].allPkgsByNameRegex( "^" + modname ):
- found = 1
-
- status, output = commands.getstatusoutput('/sbin/modinfo -F vermagic ' + modname)
-
- if status == 0:
- found = 2
-
- if len(self.fileGrep("^%s\s+" % modname, "/proc/modules")) > 0:
- found = 3
-
- if found == 0:
- self.addDiagnose("required kernel module is missing: %s" % modname)
- elif found == 1:
- self.addDiagnose("required module is not available for current kernel: %s" % modname)
- elif found == 2:
- self.addDiagnose("required module is available but not loaded: %s" % modname)
-
- for pkg in pkgs_check:
- if self.cInfo["policy"].pkgByName(pkg) == None:
- self.addDiagnose("required package is missing: %s" % pkg)
-
- if rhelver == "4":
- # (dlm, dlm-kernel) || gulm
- if not ((self.cInfo["policy"].pkgByName("dlm") and self.cInfo["policy"].pkgByName("dlm-kernel")) or self.cInfo["policy"].pkgByName("gulm")):
- self.addDiagnose("required packages are missing: (dlm, dlm-kernel) || gulm")
-
- # check if all the needed daemons are active at sosreport time
- # check if they are started at boot time in RHEL4 RHCS (cman, ccsd, rgmanager, fenced)
- # and GFS (gfs, ccsd, clvmd, fenced)
-
- for service in serv_check:
- status, output = commands.getstatusoutput("/sbin/service %s status &> /dev/null" % service)
- if status != 0:
- self.addDiagnose("service %s is not running" % service)
-
- if not self.cInfo["policy"].runlevelDefault() in self.cInfo["policy"].runlevelByService(service):
- self.addDiagnose("service %s is not started in default runlevel" % service)
-
- # FIXME: missing important cman services
- # FIXME: any cman service whose state != run ?
- # Fence Domain: "default" 2 2 run -
-
- # is cluster quorate
- if not self.is_cluster_quorate():
- self.addDiagnose("cluster node is not quorate")
-
- # if there is no cluster.conf, diagnose() finishes here.
- try:
- os.stat("/etc/cluster/cluster.conf")
- except:
- self.addDiagnose("/etc/cluster/cluster.conf is missing")
- return
-
- # setup XML xpath context
- xml = libxml2.parseFile("/etc/cluster/cluster.conf")
- xpathContext = xml.xpathNewContext()
-
- # make sure that the node names are valid according to RFC 2181
- for hostname in xpathContext.xpathEval('/cluster/clusternodes/clusternode/@name'):
- if not re.match('^[a-zA-Z]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\.[a-zA-Z]([a-zA-Z0-9-]*[a-zA-Z0-9])?)*$', hostname.content):
- self.addDiagnose("node name (%s) contains invalid characters" % hostname.content)
-
- # do not rely on DNS to resolve node names, must have them in /etc/hosts
- for hostname in xpathContext.xpathEval('/cluster/clusternodes/clusternode/@name'):
- if len(self.fileGrep(r'^.*\W+%s' % hostname.content , "/etc/hosts")) == 0:
- self.addDiagnose("node %s is not defined in /etc/hosts" % hostname.content)
-
- # check fencing (warn on no fencing)
- if len(xpathContext.xpathEval("/cluster/clusternodes/clusternode[not(fence/method/device)]")):
- if self.has_gfs():
- self.addDiagnose("one or more nodes have no fencing agent configured: fencing is required for GFS to work")
- else:
- self.addDiagnose("one or more nodes have no fencing agent configured: the cluster infrastructure might not work as intended")
-
- # check fencing (warn on manual)
- if len(xpathContext.xpathEval("/cluster/clusternodes/clusternode[/cluster/fencedevices/fencedevice[@agent='fence_manual']/@name=fence/method/device/@name]")):
- self.addDiagnose("one or more nodes have manual fencing agent configured (data integrity is not guaranteed)")
-
- # if fence_ilo or fence_drac, make sure acpid is not running
- hostname = commands.getoutput("/bin/uname -n").split(".")[0]
- if len(xpathContext.xpathEval('/cluster/clusternodes/clusternode[@name = "%s" and /cluster/fencedevices/fencedevice[@agent="fence_rsa" or @agent="fence_drac"]/@name=fence/method/device/@name]' % hostname )):
- status, output = commands.getstatusoutput("/sbin/service acpid status")
- if status == 0 or self.cInfo["policy"].runlevelDefault() in self.cInfo["policy"].runlevelByService("acpid"):
- self.addDiagnose("acpid is enabled, this may cause problems with your fencing method.")
-
- # 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 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'")
- if not status: cluster_version = cluster_version[16:]
- else: cluster_version = None
- conf_version = xpathContext.xpathEval("/cluster/@config_version")[0].content
-
- if status == 0 and conf_version != cluster_version:
- self.addDiagnose("cluster.conf and in-memory configuration version differ (%s != %s)" % (conf_version, cluster_version) )
-
- status, output = commands.getstatusoutput("/usr/sbin/rg_test test /etc/cluster/cluster.conf")
- if output.find("Error: ") > 0:
- self.addDiagnose("configuration errors are present according to rg_test")
-
- # make sure the first part of the lock table matches the cluster name
- # and that the locking protocol is sane
- cluster_name = xpathContext.xpathEval("/cluster/@name")[0].content
-
- for fs in self.fileGrep(r'^[^#][/\w]*\W*[/\w]*\W*gfs', "/etc/fstab"):
- # for each gfs entry
- fs = fs.split()
- lockproto = self.get_gfs_sb_field(fs[0], "sb_lockproto")
- if lockproto and lockproto != self.get_locking_proto():
- self.addDiagnose("gfs mountpoint (%s) is using the wrong locking protocol (%s)" % (fs[0], lockproto) )
-
- locktable = self.get_gfs_sb_field(fs[0], "sb_locktable")
- try: locktable = locktable.split(":")[0]
- except: continue
- if locktable != cluster_name:
- self.addDiagnose("gfs mountpoint (%s) is using the wrong locking table" % fs[0])
+ try: rhelver = self.cInfo["policy"].pkgByName("redhat-release")[1]
+ except: rhelver = None
+
+ # FIXME: we should only run tests specific for the version, now just do them all regardless
+ if rhelver.startswith("5"):
+ # check that kernel module packages are installed for
+ # running kernel version
+ pkgs_check = [ ]
+ if self.has_gfs(): pkgs_check.append("kmod-gfs")
+
+ for pkgname in pkgs_check:
+ if not self.cInfo["policy"].pkgByName(pkgname):
+ self.addDiagnose("required package is missing: %s" % pkgname)
+
+ # check if the minimum set of packages is installed
+ # for RHEL4 RHCS(ccs, cman, cman-kernel, magma, magma-plugins, (dlm, dlm-kernel) || gulm, perl-Net-Telnet, rgmanager, fence)
+ # RHEL4 GFS (GFS, GFS-kernel, ccs, lvm2-cluster, fence)
+
+ for pkg in [ "cman", "perl-Net-Telnet", "rgmanager" ]:
+ if self.cInfo["policy"].pkgByName(pkg) == None:
+ self.addDiagnose("required package is missing: %s" % pkg)
+
+ # let's make modules sure are loaded
+ mods_check = [ "dlm" ]
+ if self.has_gfs(): mods_check.append("gfs")
+ for module in mods_check:
+ if len(self.fileGrep("^%s " % module, "/proc/modules")) == 0:
+ self.addDiagnose("required module is not loaded: %s" % module)
+
+ # check if all the needed daemons are active at sosreport time
+ # check if they are started at boot time in RHEL5 RHCS (rgmanager, cman)
+ # and GFS (gfs, ccsd, clvmd, fenced)
+ checkserv = [ "cman", "rgmanager" ]
+ if self.has_gfs(): checkserv.extend( ["gfs", "clvmd"] )
+ for service in checkserv:
+ status, output = commands.getstatusoutput("/sbin/service %s status" % service)
+ if status:
+ self.addDiagnose("service %s is not running" % service)
+
+ if not self.cInfo["policy"].runlevelDefault() in self.cInfo["policy"].runlevelByService(service):
+ self.addDiagnose("service %s is not started in default runlevel" % service)
+
+ # FIXME: any cman service whose state != run ?
+ # Fence Domain: "default" 2 2 run -
+
+ # is cluster quorate
+ if not self.is_cluster_quorate():
+ self.addDiagnose("cluster node is not quorate")
+
+ # if there is no cluster.conf, diagnose() finishes here.
+ try:
+ os.stat("/etc/cluster/cluster.conf")
+ except:
+ self.addDiagnose("/etc/cluster/cluster.conf is missing")
+ return
+
+ # setup XML xpath context
+ xml = libxml2.parseFile("/etc/cluster/cluster.conf")
+ xpathContext = xml.xpathNewContext()
+
+ # check fencing (warn on no fencing)
+ if len(xpathContext.xpathEval("/cluster/clusternodes/clusternode[not(fence/method/device)]")):
+ if self.has_gfs():
+ self.addDiagnose("one or more nodes have no fencing agent configured: fencing is required for GFS to work")
+ else:
+ self.addDiagnose("one or more nodes have no fencing agent configured: the cluster infrastructure might not work as intended")
+
+ # check fencing (warn on manual)
+ if len(xpathContext.xpathEval("/cluster/clusternodes/clusternode[/cluster/fencedevices/fencedevice[@agent='fence_manual']/@name=fence/method/device/@name]")):
+ self.addDiagnose("one or more nodes have manual fencing agent configured (data integrity is not guaranteed)")
+
+ # if fence_ilo or fence_drac, make sure acpid is not running
+ hostname = commands.getoutput("/bin/uname -n").split(".")[0]
+ if len(xpathContext.xpathEval('/cluster/clusternodes/clusternode[@name = "%s" and /cluster/fencedevices/fencedevice[@agent="fence_rsa" or @agent="fence_drac"]/@name=fence/method/device/@name]' % hostname )):
+ status, output = commands.getstatusoutput("/sbin/service acpid status")
+ if status == 0 or self.cInfo["policy"].runlevelDefault() in self.cInfo["policy"].runlevelByService("acpid"):
+ self.addDiagnose("acpid is enabled, this may cause problems with your fencing method.")
+
+ # 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 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'")
+ if not status: cluster_version = cluster_version[16:]
+ else: cluster_version = None
+ conf_version = xpathContext.xpathEval("/cluster/@config_version")[0].content
+
+ if status == 0 and conf_version != cluster_version:
+ self.addDiagnose("cluster.conf and in-memory configuration version differ (%s != %s)" % (conf_version, cluster_version) )
+
+ # make sure the first part of the lock table matches the cluster name
+ # and that the locking protocol is sane
+ cluster_name = xpathContext.xpathEval("/cluster/@name")[0].content
+
+ for fs in self.fileGrep(r'^[^#][/\w]*\W*[/\w]*\W*gfs', "/etc/fstab"):
+ # for each gfs entry
+ fs = fs.split()
+
+ lockproto = self.get_gfs_sb_field(fs[0], "sb_lockproto")
+ if lockproto and lockproto != self.get_locking_proto():
+ self.addDiagnose("gfs mountpoint (%s) is using the wrong locking protocol (%s)" % (fs[0], lockproto) )
+
+ locktable = self.get_gfs_sb_field(fs[0], "sb_locktable")
+ try: locktable = locktable.split(":")[0]
+ except: continue
+ if locktable != cluster_name:
+ self.addDiagnose("gfs mountpoint (%s) is using the wrong locking table" % fs[0])
def setup(self):
self.collectExtOutput("/sbin/fdisk -l")
@@ -214,9 +175,9 @@ class cluster(sos.plugintools.PluginBase):
self.collectExtOutput("/sbin/ipvsadm -L")
- if self.getOption('gfslockdump'): self.do_gfslockdump()
- if self.getOption('lockdump'): self.do_lockdump()
- if self.getOption('taskdump'): self.do_taskdump()
+ if self.isOptionEnabled('gfslockdump'): self.do_gfslockdump()
+ if self.isOptionEnabled('lockdump'): self.do_lockdump()
+ if self.isOptionEnabled('taskdump'): self.do_taskdump()
return
@@ -233,24 +194,20 @@ class cluster(sos.plugintools.PluginBase):
self.addCopySpec("/var/log/messages")
def do_lockdump(self):
- status, output = commands.getstatusoutput("cman_tool services")
- if status:
- # command somehow failed
- return False
-
- import re
-
- rhelver = self.get_redhat_release()
-
- if rhelver == "4":
- regex = r'^DLM Lock Space:\s*"([^"]*)".*$'
- elif rhelver == "5Server" or rhelver == "5Client":
- regex = r'^dlm\s+[^\s]+\s+([^\s]+)\s.*$'
-
- reg=re.compile(regex,re.MULTILINE)
- for lockspace in reg.findall(output):
- commands.getstatusoutput("echo %s > /proc/cluster/dlm_locks" % lockspace)
- self.collectOutputNow("cat /proc/cluster/dlm_locks", root_symlink = "dlm_locks_%s" % lockspace)
+ try:
+ fp = open("/proc/cluster/services","r")
+ except:
+ return
+ for line in fp.readlines():
+ if line[0:14] == "DLM Lock Space":
+ try:
+ lockspace = line.split('"')[1]
+ except:
+ pass
+ else:
+ commands.getstatusoutput("echo %s > /proc/cluster/dlm_locks" % lockspace)
+ self.collectOutputNow("cat /proc/cluster/dlm_locks", root_symlink = "dlm_locks_%s" % lockspace)
+ fp.close()
def get_locking_proto(self):
# FIXME: what's the best way to find out ?
@@ -258,11 +215,15 @@ class cluster(sos.plugintools.PluginBase):
return "lock_gulm"
def do_gfslockdump(self):
- for mntpoint in self.doRegexFindAll(r'^\S+\s+([^\s]+)\s+gfs\s+.*$', "/proc/mounts"):
- self.collectExtOutput("/sbin/gfs_tool lockdump %s" % mntpoint, root_symlink = "gfs_lockdump_" + self.mangleCommand(mntpoint) )
-
- def do_rgmanager_bt(self):
- # FIXME: threads backtrace via SIGALRM
+ fp = open("/proc/mounts","r")
+ for line in fp.readlines():
+ mntline = line.split(" ")
+ if mntline[2] == "gfs":
+ self.collectExtOutput("/sbin/gfs_tool lockdump %s" % mntline[1], root_symlink = "gfs_lockdump_" + self.mangleCommand(mntline[1]) )
+ fp.close()
+
+ def do_rgmgr_bt(self):
+ # FIXME: threads backtrace
return
def postproc(self):
@@ -272,7 +233,7 @@ class cluster(sos.plugintools.PluginBase):
def is_cluster_quorate(self):
output = commands.getoutput("cman_tool status | grep '^Membership state: '")
try:
- if output[18:] == "Cluster-Member":
+ if output.split(":")[1].strip() == "Cluster-Member":
return True
else:
return False
diff --git a/src/lib/sos/plugins/devicemapper.py b/src/lib/sos/plugins/devicemapper.py
index 5a1b63c2..38009689 100644
--- a/src/lib/sos/plugins/devicemapper.py
+++ b/src/lib/sos/plugins/devicemapper.py
@@ -22,6 +22,11 @@ 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")
@@ -40,18 +45,17 @@ class devicemapper(sos.plugintools.PluginBase):
self.addCopySpec("/var/lib/multipath/bindings")
self.collectExtOutput("/sbin/multipath -v4 -ll")
- self.collectExtOutput("/usr/bin/systool -v -C -b scsi")
+ self.collectExtOutput("/usr/bin/systool -v -c -b scsi")
self.collectExtOutput("/bin/ls -laR /dev")
self.collectExtOutput("/bin/ls -laR /sys/block")
if self.getOption('lvmdump'):
- sosGetCommandOutput("lvmdump -d %s" % os.path.join(self.cInfo['dstroot'],"lvmdump"))
+ self.do_lvmdump()
- 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))
+ 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/emc.py b/src/lib/sos/plugins/emc.py
index 24b3e04c..16f039a8 100644
--- a/src/lib/sos/plugins/emc.py
+++ b/src/lib/sos/plugins/emc.py
@@ -37,7 +37,7 @@ class emc(sos.plugintools.PluginBase):
def get_pp_files(self):
""" EMC PowerPath specific information - files
"""
- self.collectExtOutput("/sbin/powermt version")
+ self.collectExtOutput("/sbin/powermt version")
self.addCopySpec("/etc/init.d/PowerPath")
self.addCopySpec("/etc/powermt.custom")
self.addCopySpec("/etc/emcp_registration")
@@ -50,7 +50,7 @@ class emc(sos.plugintools.PluginBase):
return
def get_pp_config(self):
- """ EMC PowerPath specific information - commands
+ """ EMC PowerPath specific information - commands
"""
self.collectExtOutput("/sbin/powermt display")
self.collectExtOutput("/sbin/powermt display dev=all")
@@ -59,12 +59,12 @@ class emc(sos.plugintools.PluginBase):
self.collectExtOutput("/sbin/powermt display ports")
self.collectExtOutput("/sbin/powermt display paths")
self.collectExtOutput("/sbin/powermt dump")
- return
+ return
def get_symcli_files(self):
""" EMC Solutions Enabler SYMCLI specific information - files
"""
- self.addCopySpec("/var/symapi/db/symapi_db.bin")
+ self.addCopySpec("/var/symapi/db/symapi_db.bin")
self.addCopySpec("/var/symapi/config/[a-z]*")
self.addCopySpec("/var/symapi/log/[a-z]*")
return
@@ -116,7 +116,7 @@ class emc(sos.plugintools.PluginBase):
self.collectExtOutput("/usr/symcli/bin/symmask list hba")
self.collectExtOutput("/usr/symcli/bin/symmask list logins")
self.collectExtOutput("/usr/symcli/bin/symmaskdb list database")
- self.collectExtOutput("/usr/symcli/bin/symmaskdb -v list database")
+ self.collectExtOutput("/usr/symcli/bin/symmaskdb -v list database")
return
def get_navicli_config(self):
@@ -139,14 +139,14 @@ class emc(sos.plugintools.PluginBase):
self.collectExtOutput("/opt/Navisphere/bin/navicli -h %s getdisk" % SP_address)
self.collectExtOutput("/opt/Navisphere/bin/navicli -h %s getcache" % SP_address)
self.collectExtOutput("/opt/Navisphere/bin/navicli -h %s getlun" % SP_address)
- self.collectExtOutput("/opt/Navisphere/bin/navicli -h %s getlun -rg -type -default -owner -crus -capacity" % SP_address)
+ self.collectExtOutput("/opt/Navisphere/bin/navicli -h %s getlun -rg -type -default -owner -crus -capacity" % SP_address)
self.collectExtOutput("/opt/Navisphere/bin/navicli -h %s lunmapinfo" % SP_address)
self.collectExtOutput("/opt/Navisphere/bin/navicli -h %s getcrus" % SP_address)
self.collectExtOutput("/opt/Navisphere/bin/navicli -h %s port -list -all" % SP_address)
self.collectExtOutput("/opt/Navisphere/bin/navicli -h %s storagegroup -list" % SP_address)
self.collectExtOutput("/opt/Navisphere/bin/navicli -h %s spportspeed -get" % SP_address)
return
-
+
def setup(self):
## About EMC Corporation default no if no EMC products are installed
add_about_emc="no"
@@ -184,9 +184,9 @@ class emc(sos.plugintools.PluginBase):
self.get_navicli_config()
print " Gathering Navisphere NAVICLI Host Agent information..."
print " Please enter a CLARiiON SP IP address. In order to collect"
- print " information for both SPA and SPB as well as multiple"
+ print " information for both SPA and SPB as well as multiple"
print " CLARiiON arrays (if desired) you will be prompted multiple times."
- print " To exit simply press [Enter]"
+ print " To exit simply press [Enter]"
print ""
add_about_emc = "yes"
CLARiiON_IP_address_list = []
@@ -194,23 +194,23 @@ class emc(sos.plugintools.PluginBase):
while CLARiiON_IP_loop == "stay_in":
ans = raw_input("CLARiiON SP IP Address or [Enter] to exit: ")
## Check to make sure the CLARiiON SP IP address provided is valid
- status, output = commands.getstatusoutput("/opt/Navisphere/bin/navicli -h %s getsptime" % ans)
- if status == 0:
+ status, output = commands.getstatusoutput("/opt/Navisphere/bin/navicli -h %s getsptime" % ans)
+ if status == 0:
CLARiiON_IP_address_list.append(ans)
else:
if ans != "":
- print "The IP address you entered, %s, is not to an active CLARiiON SP." % ans
+ print "The IP address you entered, %s, is not to an active CLARiiON SP." % ans
if ans == "":
CLARiiON_IP_loop = "get_out"
## Sort and dedup the list of CLARiiON IP Addresses
CLARiiON_IP_address_list.sort()
for SP_address in CLARiiON_IP_address_list:
if CLARiiON_IP_address_list.count(SP_address) > 1:
- CLARiiON_IP_address_list.remove(SP_address)
+ CLARiiON_IP_address_list.remove(SP_address)
for SP_address in CLARiiON_IP_address_list:
if SP_address != "":
print " Gathering NAVICLI information for %s..." % SP_address
- self.get_navicli_SP_info(SP_address)
+ self.get_navicli_SP_info(SP_address)
## Only provide About EMC if EMC products are installed
if add_about_emc != "no":
diff --git a/src/lib/sos/plugins/filesys.py b/src/lib/sos/plugins/filesys.py
index 3e3a7fba..bec046f2 100644
--- a/src/lib/sos/plugins/filesys.py
+++ b/src/lib/sos/plugins/filesys.py
@@ -13,7 +13,7 @@
## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
import sos.plugintools
-import os
+import commands
class filesys(sos.plugintools.PluginBase):
"""information on filesystems
@@ -29,11 +29,12 @@ class filesys(sos.plugintools.PluginBase):
self.addCopySpec("/etc/mdadm.conf")
self.collectExtOutput("/bin/df -al", root_symlink = "df")
+ self.collectExtOutput("/usr/sbin/lsof -b +M -n -l", root_symlink = "lsof")
self.collectExtOutput("/sbin/blkid")
-
+
self.collectExtOutput("/sbin/fdisk -l", root_symlink = "fdisk-l")
for extfs in self.doRegexFindAll(r"^(/dev/.+) on .+ type ext.\s+", mounts):
self.collectExtOutput("/sbin/dumpe2fs %s" % (extfs))
-
return
+
diff --git a/src/lib/sos/plugins/general.py b/src/lib/sos/plugins/general.py
index 434bfdaa..062e0674 100644
--- a/src/lib/sos/plugins/general.py
+++ b/src/lib/sos/plugins/general.py
@@ -20,35 +20,25 @@ class general(sos.plugintools.PluginBase):
"""basic system information
"""
- optionList = [("syslogsize", "max size (MiB) to collect per syslog file", "", 15),
- ("all_logs", "collect all log files defined in syslog.conf", "", False)]
+ optionList = [("syslogsize", "max size (MiB) to collect per syslog file", "", 15)]
def setup(self):
self.addCopySpec("/etc/redhat-release")
self.addCopySpec("/etc/fedora-release")
- self.addCopySpec("/etc/inittab")
- self.addCopySpec("/etc/sos.conf")
self.addCopySpec("/etc/sysconfig")
self.addCopySpec("/proc/stat")
self.addCopySpec("/var/log/dmesg")
self.addCopySpec("/var/log/messages")
- self.addCopySpecLimit("/var/log/messages.*", sizelimit = self.getOption("syslogsize"))
+ self.addCopySpecLimit("/var/log/messages.*", sizelimit = self.isOptionEnabled("syslogsize"))
self.addCopySpec("/var/log/secure")
- self.addCopySpecLimit("/var/log/secure.*", sizelimit = self.getOption("syslogsize"))
+ 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")
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)
-
+ self.addCopySpec("/root/anaconda-ks.cfg")
return
def postproc(self):
diff --git a/src/lib/sos/plugins/hardware.py b/src/lib/sos/plugins/hardware.py
index ad4a5537..ba10a356 100644
--- a/src/lib/sos/plugins/hardware.py
+++ b/src/lib/sos/plugins/hardware.py
@@ -36,12 +36,23 @@ 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 -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("""/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("/usr/sbin/dmidecode", root_symlink = "dmidecode")
- if self.cInfo["policy"].getArch().endswith("386"):
- self.collectExtOutput("/usr/sbin/x86info -a")
+ # 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:])
self.collectExtOutput("/sbin/lsusb")
self.collectExtOutput("/usr/bin/lshal")
diff --git a/src/lib/sos/plugins/initrd.py b/src/lib/sos/plugins/initrd.py
index 7bd7e1f3..83356548 100644
--- a/src/lib/sos/plugins/initrd.py
+++ b/src/lib/sos/plugins/initrd.py
@@ -20,9 +20,9 @@ class initrd(sos.plugintools.PluginBase):
"""
def setup(self):
for initrd in glob.glob('/boot/initrd-*.img'):
- self.collectExtOutput("/bin/zcat "+initrd+" | /bin/cpio "+
+ self.collectExtOutput("/bin/zcat "+initrd+" | /bin/cpio "+
"--extract --to-stdout init" )
return
def defaultenabled(self):
- return False
+ return False
diff --git a/src/lib/sos/plugins/kernel.py b/src/lib/sos/plugins/kernel.py
index 4fb0a864..8ca53b66 100644
--- a/src/lib/sos/plugins/kernel.py
+++ b/src/lib/sos/plugins/kernel.py
@@ -18,7 +18,7 @@ import commands, os, re
class kernel(sos.plugintools.PluginBase):
"""kernel related information
"""
- optionList = [("modinfo", 'gathers information on all kernel modules', 'fast', True),
+ optionList = [("modinfo", 'gathers module information on all modules', 'fast', True),
('sysrq', 'trigger sysrq+[m,p,t] dumps', 'fast', False)]
moduleFile = ""
taintList = [
@@ -28,7 +28,7 @@ class kernel(sos.plugintools.PluginBase):
{'regex':'vxportal*', 'description':'Veritas module'},
{'regex':'vxdmp*', 'description':'Veritas dynamic multipathing module'},
{'regex':'vxio*', 'description':'Veritas module'},
- {'regex':'vxspec*', 'description':'Veritas module'},
+ {'regex':'vxspec*"', 'description':'Veritas module'},
{'regex':'dcd*', 'description':'Dell OpenManage Server Administrator module'},
{'regex':'ocfs', 'description':'Oracle cluster filesystem module'},
{'regex':'oracle*', 'description':'Oracle module'},
@@ -49,22 +49,22 @@ class kernel(sos.plugintools.PluginBase):
def setup(self):
self.collectExtOutput("/bin/uname -a", root_symlink = "uname")
self.moduleFile = self.collectOutputNow("/sbin/lsmod", root_symlink = "lsmod")
-
- if self.getOption('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 = runcmd + " " + kmod
- if len(runcmd):
- self.collectExtOutput("/sbin/modinfo " + runcmd)
-
+ 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 = runcmd + " " + kmod
+ if len(runcmd):
+ self.collectExtOutput("/sbin/modinfo " + runcmd)
self.collectExtOutput("/sbin/sysctl -a")
self.collectExtOutput("/sbin/ksyms")
self.addCopySpec("/sys/module/*/parameters")
self.addCopySpec("/proc/filesystems")
self.addCopySpec("/proc/ksyms")
self.addCopySpec("/proc/slabinfo")
- self.addCopySpec("/lib/modules/%s/modules.dep" % self.cInfo["policy"].kernelVersion())
+ kver = commands.getoutput('/bin/uname -r')
+ depfile = "/lib/modules/%s/modules.dep" % (kver,)
+ self.addCopySpec(depfile)
self.addCopySpec("/etc/conf.modules")
self.addCopySpec("/etc/modules.conf")
self.addCopySpec("/etc/modprobe.conf")
@@ -72,18 +72,25 @@ class kernel(sos.plugintools.PluginBase):
self.addCopySpec("/proc/cmdline")
self.addCopySpec("/proc/driver")
self.addCopySpec("/proc/sys/kernel/tainted")
-
- if self.getOption('sysrq') and os.access("/proc/sysrq-trigger", os.W_OK):
- for key in ['m', 'p', 't']:
- commands.getoutput("/bin/echo %s > /proc/sysrq-trigger" % (key,))
- self.addCopySpec("/var/log/messages")
-
+ # FIXME: both RHEL4 and RHEL5 don't need sysrq to be enabled to trigger via sysrq-trigger
+ if self.isOptionEnabled('sysrq') and os.access("/proc/sysrq-trigger", os.W_OK) and os.access("/proc/sys/kernel/sysrq", os.R_OK):
+ sysrq_state = commands.getoutput("/bin/cat /proc/sys/kernel/sysrq")
+ commands.getoutput("/bin/echo 1 > /proc/sys/kernel/sysrq")
+ for key in ['m', 'p', 't']:
+ commands.getoutput("/bin/echo %s > /proc/sysrq-trigger" % (key,))
+ 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")
+
return
- def diagnose(self):
-
+ def analyze(self):
infd = open("/proc/modules", "r")
- for modname in infd.readlines():
+ modules = infd.readlines()
+ infd.close()
+
+ for modname in modules:
modname=modname.split(" ")[0]
modinfo_srcver = commands.getoutput("/sbin/modinfo -F srcversion %s" % modname)
if not os.access("/sys/module/%s/srcversion" % modname, os.R_OK):
@@ -92,17 +99,13 @@ class kernel(sos.plugintools.PluginBase):
sys_srcver = infd.read().strip("\n")
infd.close()
if modinfo_srcver != sys_srcver:
- self.addDiagnose("loaded module %s differs from the one present on the file-system" % modname)
+ self.addAlert("Loaded module %s differs from the one present on the file-system")
# this would be a good moment to check the module's signature
# but at the moment there's no easy way to do that outside of
# the kernel. i will probably need to write a C lib (derived from
# the kernel sources to do this verification.
- infd.close()
-
- def analyze(self):
-
savedtaint = os.path.join(self.cInfo['dstroot'], "/proc/sys/kernel/tainted")
infd = open(savedtaint, "r")
line = infd.read()
@@ -111,10 +114,12 @@ class kernel(sos.plugintools.PluginBase):
if (line != "0"):
self.addAlert("Kernel taint flag is <%s>\n" % line)
+
infd = open(self.moduleFile, "r")
modules = infd.readlines()
infd.close()
+ #print(modules)
for tainter in self.taintList:
p = re.compile(tainter['regex'])
for line in modules:
diff --git a/src/lib/sos/plugins/ldap.py b/src/lib/sos/plugins/ldap.py
index b1a48420..318a3ba9 100644
--- a/src/lib/sos/plugins/ldap.py
+++ b/src/lib/sos/plugins/ldap.py
@@ -13,37 +13,14 @@
## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
import sos.plugintools
-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?
- ldapopts=["URI","BASE","TLS_CACERTDIR"]
- results={}
- tmplist=[]
- for i in ldapopts:
- t=self.doRegexFindAll(r"^(%s)\s+(.*)" % i,"/etc/openldap/ldap.conf")
- for x in t:
- results[x[0]]=x[1].rstrip("\n")
- return results
-
- def diagnose(self):
- # Validate ldap client options
- ldapopts=self.get_ldap_opts()
- if ldapopts.has_key("TLS_CACERTDIR") and not 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")
+ return
def postproc(self):
self.doRegexSub("/etc/ldap.conf", r"(\s*bindpw\s*)\S+", r"\1***")
diff --git a/src/lib/sos/plugins/named.py b/src/lib/sos/plugins/named.py
index bb0d079e..421143cb 100644
--- a/src/lib/sos/plugins/named.py
+++ b/src/lib/sos/plugins/named.py
@@ -20,14 +20,21 @@ class named(sos.plugintools.PluginBase):
"""named related information
"""
def checkenabled(self):
- self.files = [ "/etc/named.conf", "/etc/sysconfig/named" ]
- self.packages = [ "bind", "bind-chroot" ]
- return sos.plugintools.PluginBase.checkenabled(self)
+ if self.cInfo["policy"].pkgByName("bind") or os.path.exists("/etc/named.conf") or os.path.exists("/etc/sysconfig/named"):
+ return True
+ return False
def setup(self):
- self.addCopySpec("/etc/named.boot")
- self.addCopySpec("/etc/named.conf")
- self.addCopySpec("/etc/sysconfig/named")
- self.addCopySpec("/var/named")
- self.addForbiddenPath('/var/named/chroot/proc')
- self.addForbiddenPath('/var/named/chroot/dev')
+ dnsdir = ""
+ self.addCopySpec("/etc/named.boot")
+ self.addCopySpec("/etc/named.conf")
+ self.addCopySpec("/etc/sysconfig/named")
+ 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')
+ return
diff --git a/src/lib/sos/plugins/networking.py b/src/lib/sos/plugins/networking.py
index 164ed43a..080ae694 100644
--- a/src/lib/sos/plugins/networking.py
+++ b/src/lib/sos/plugins/networking.py
@@ -24,7 +24,14 @@ class networking(sos.plugintools.PluginBase):
"""Return a dictionary for which key are interface name according to the
output of ifconifg-a stored in ifconfigFile.
"""
- out=self.doRegexFindAll(r"^(eth\d+)\D", ifconfigFile)
+ out={}
+ if(os.path.isfile(ifconfigFile)):
+ f=open(ifconfigFile,'r')
+ content=f.read()
+ f.close()
+ reg=re.compile(r"^(eth\d+)\D",re.MULTILINE)
+ for name in reg.findall(content):
+ out[name]=1
return out
def collectIPTable(self,tablename):
@@ -53,19 +60,20 @@ class networking(sos.plugintools.PluginBase):
self.addCopySpec("/etc/resolv.conf")
ifconfigFile=self.collectOutputNow("/sbin/ifconfig -a", root_symlink = "ifconfig")
self.collectExtOutput("/sbin/route -n", root_symlink = "route")
+ self.collectExtOutput("/sbin/ipchains -nvL")
self.collectIPTable("filter")
self.collectIPTable("nat")
self.collectIPTable("mangle")
self.collectExtOutput("/bin/netstat -s")
self.collectExtOutput("/bin/netstat -neopa", root_symlink = "netstat")
- self.collectExtOutput("/sbin/ip route show table all")
+ # FIXME: we should collect "ip route table <tablename>" for all tables (from "ip rule")
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.getOption("traceroute"):
+ if self.isOptionEnabled("traceroute"):
self.collectExtOutput("/bin/traceroute -n rhn.redhat.com")
return
diff --git a/src/lib/sos/plugins/nfsserver.py b/src/lib/sos/plugins/nfsserver.py
index 1e352032..9564aa22 100644
--- a/src/lib/sos/plugins/nfsserver.py
+++ b/src/lib/sos/plugins/nfsserver.py
@@ -35,10 +35,7 @@ class nfsserver(sos.plugintools.PluginBase):
def setup(self):
self.addCopySpec("/etc/exports")
- self.addCopySpec("/var/lib/nfs/etab")
- self.addCopySpec("/var/lib/nfs/xtab")
- self.addCopySpec("/var/lib/nfs/rmtab")
self.collectExtOutput("/usr/sbin/rpcinfo -p localhost")
- self.collectExtOutput("/usr/sbin/nfsstat -a")
+ self.collectExtOutput("/usr/sbin/nfsstat")
return
diff --git a/src/lib/sos/plugins/pam.py b/src/lib/sos/plugins/pam.py
index 1a50811b..8164bba3 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")
+ self.collectExtOutput("/bin/ls -laF /lib/security/pam_*so")
return
diff --git a/src/lib/sos/plugins/process.py b/src/lib/sos/plugins/process.py
index 0d89e06b..47e37edf 100644
--- a/src/lib/sos/plugins/process.py
+++ b/src/lib/sos/plugins/process.py
@@ -25,7 +25,6 @@ class process(sos.plugintools.PluginBase):
self.collectExtOutput("/bin/ps auxwwwm")
self.collectExtOutput("/bin/ps alxwww")
self.collectExtOutput("/usr/bin/pstree", root_symlink = "pstree")
- self.collectExtOutput("/usr/sbin/lsof -b +M -n -l", root_symlink = "lsof")
return
def find_mountpoint(s):
@@ -41,7 +40,7 @@ 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.
diff --git a/src/lib/sos/plugins/rpm.py b/src/lib/sos/plugins/rpm.py
index f1c09e33..d9f1e79b 100644
--- a/src/lib/sos/plugins/rpm.py
+++ b/src/lib/sos/plugins/rpm.py
@@ -22,12 +22,12 @@ class rpm(sos.plugintools.PluginBase):
def setup(self):
self.addCopySpec("/var/log/rpmpkgs")
-
- if self.getOption("rpmq"):
- self.collectExtOutput("/bin/rpm -qa --qf \"%{NAME}-%{VERSION}-%{RELEASE}-%{ARCH}\n\"", root_symlink = "installed-rpms")
-
- if self.getOption("rpmva"):
- self.eta_weight += 1500 # this plugins takes 200x longer (for ETA)
- self.collectExtOutput("/bin/rpm -Va", root_symlink = "rpm-Va", timeout = 3600)
+
+ if self.isOptionEnabled("rpmq"):
+ self.collectExtOutput("/bin/rpm -qa --qf=\"%{NAME}-%{VERSION}-%{RELEASE}-%{ARCH}~~%{INSTALLTIME:date}\n\"|/bin/awk -F ~~ '{printf \"%-60s%s\\n\",$1,$2}'", 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/selinux.py b/src/lib/sos/plugins/selinux.py
index 5f0c1f40..897c3991 100644
--- a/src/lib/sos/plugins/selinux.py
+++ b/src/lib/sos/plugins/selinux.py
@@ -19,32 +19,18 @@ class selinux(sos.plugintools.PluginBase):
"""selinux related information
"""
def setup(self):
- # sestatus is always collected in checkenabled()
- self.addCopySpec("/etc/selinux")
+ self.addCopySpec("/etc/selinux/*")
self.collectExtOutput("/usr/bin/selinuxconfig")
- self.eta_weight += 120 # this plugins takes 120x longer (for ETA)
- self.collectExtOutput("/sbin/fixfiles check")
-
- self.addForbiddenPath("/etc/selinux/targeted")
-
+ self.collectExtOutput("/usr/sbin/sestatus", root_symlink = "sestatus")
+ self.collectExtOutput("/bin/rpm -q -V selinux-policy-targeted")
+ self.collectExtOutput("/bin/rpm -q -V selinux-policy-strict")
return
def checkenabled(self):
# is selinux enabled ?
try:
- if self.collectOutputNow("/usr/sbin/sestatus", root_symlink = "sestatus").split(":")[1].strip() == "disabled":
+ if commands.getoutput("/usr/sbin/sestatus").split(":")[1].strip() == "disabled":
return False
except:
pass
return True
-
- def analyze(self):
- # Check for SELinux denials and capture raw output from sealert
- if self.cInfo["policy"].runlevelDefault() in self.cInfo["policy"].runlevelByService("setroubleshoot"):
- # TODO: fixup regex for more precise matching
- sealert=doRegexFindAll(r"^.*setroubleshoot:.*(sealert\s-l\s.*)","/var/log/messages")
- if sealert:
- for i in sealert:
- self.collectExtOutput("%s" % i)
- self.addAlert("There are numerous selinux errors present and "+
- "possible fixes stated in the sealert output.")
diff --git a/src/lib/sos/plugins/squid.py b/src/lib/sos/plugins/squid.py
index 7de66100..fdd3b8cf 100644
--- a/src/lib/sos/plugins/squid.py
+++ b/src/lib/sos/plugins/squid.py
@@ -19,12 +19,11 @@ class squid(sos.plugintools.PluginBase):
"""squid related information
"""
def checkenabled(self):
- self.files = [ "/etc/squid/squid.conf" ]
- self.packages = [ "squid" ]
- return sos.plugintools.PluginBase.checkenabled(self)
+ if self.cInfo["policy"].pkgByName("squid") != None or os.path.exists("/etc/squid/squid.conf"):
+ return True
+ return False
def setup(self):
self.addCopySpec("/etc/squid/squid.conf")
- self.addCopySpec("/var/log/squid")
return
diff --git a/src/lib/sos/plugins/startup.py b/src/lib/sos/plugins/startup.py
index a0d3e400..59014aaa 100644
--- a/src/lib/sos/plugins/startup.py
+++ b/src/lib/sos/plugins/startup.py
@@ -19,6 +19,7 @@ class startup(sos.plugintools.PluginBase):
"""
def setup(self):
self.addCopySpec("/etc/rc.d")
+
self.collectExtOutput("/sbin/chkconfig --list", root_symlink = "chkconfig")
self.collectExtOutput("/sbin/runlevel")
return
diff --git a/src/lib/sos/plugins/systemtap.py b/src/lib/sos/plugins/systemtap.py
index 0f5dda19..b99ce0cf 100644
--- a/src/lib/sos/plugins/systemtap.py
+++ b/src/lib/sos/plugins/systemtap.py
@@ -17,15 +17,13 @@
import sos.plugintools
class systemtap(sos.plugintools.PluginBase):
- """SystemTap information
+ """SystemTap pre-requisites information
"""
- def checkenabled(self):
- self.files = [ "/usr/bin/stap" ]
- self.packages = [ "systemtap", "systemtap-runtime" ]
- return sos.plugintools.PluginBase.checkenabled(self)
-
def setup(self):
# requires systemtap, systemtap-runtime, kernel-devel,
# kernel-debuginfo, kernel-debuginfo-common
+ self.collectExtOutput("/bin/rpm -qa | /bin/egrep -e kernel.*`uname -r` -e systemtap -e elfutils | sort")
self.collectExtOutput("/usr/bin/stap -V 2")
+ self.collectExtOutput("/bin/uname -r")
return
+
diff --git a/src/lib/sos/plugins/x11.py b/src/lib/sos/plugins/x11.py
index 755352ef..4abd8782 100644
--- a/src/lib/sos/plugins/x11.py
+++ b/src/lib/sos/plugins/x11.py
@@ -19,19 +19,16 @@ class x11(sos.plugintools.PluginBase):
"""X related information
"""
def checkenabled(self):
- try:os.stat("/etc/X11")
- except:pass
- else:return True
- return False
+ try: os.stat("/etc/X11")
+ except: pass
+ else: return True
+
+ return False
def setup(self):
self.addCopySpec("/etc/X11")
self.addCopySpec("/var/log/Xorg.*.log")
self.addCopySpec("/var/log/XFree86.*.log")
self.collectExtOutput("/bin/dmesg | grep -e 'agpgart.'")
-
- self.addForbiddenPath("/etc/X11/X")
- self.addForbiddenPath("/etc/X11/fontpath.d")
-
return
diff --git a/src/lib/sos/plugins/xen.py b/src/lib/sos/plugins/xen.py
index 89ed359f..28c0ed43 100644
--- a/src/lib/sos/plugins/xen.py
+++ b/src/lib/sos/plugins/xen.py
@@ -38,6 +38,11 @@ class xen(sos.plugintools.PluginBase):
return False
return True
+ def is_running_xenstored(self):
+ xs_pid = os.popen("pidof xenstored").read()
+ xs_pidnum = re.split('\n$',xs_pid)[0]
+ return xs_pidnum.isdigit()
+
def domCollectProc(self):
self.addCopySpec("/proc/xen/balloon")
self.addCopySpec("/proc/xen/capabilities")
@@ -68,10 +73,17 @@ class xen(sos.plugintools.PluginBase):
self.collectExtOutput("/usr/sbin/xm info")
self.collectExtOutput("/usr/sbin/brctl show")
self.domCollectProc()
- # work-around for BZ#371251 which eventually needs to be fixed in xen
- status, output = commands.getstatusoutput("/sbin/service xend status &> /dev/null")
- if status == 0:
- self.addCopySpec("/sys/hypervisor")
+ self.addCopySpec("/sys/hypervisor/version")
+ self.addCopySpec("/sys/hypervisor/compilation")
+ self.addCopySpec("/sys/hypervisor/properties")
+ self.addCopySpec("/sys/hypervisor/type")
+ if is_xenstored_running():
+ self.addCopySpec("/sys/hypervisor/uuid")
+ self.collectExtOutput("/usr/bin/xenstore-ls")
+ else:
+ # we need tdb instead of xenstore-ls if cannot get it.
+ self.addCopySpec("/var/lib/xenstored/tdb")
+
# FIXME: we *might* want to collect things in /sys/bus/xen*,
# /sys/class/xen*, /sys/devices/xen*, /sys/modules/blk*,
# /sys/modules/net*, but I've never heard of them actually being
diff --git a/src/lib/sos/plugins/yum.py b/src/lib/sos/plugins/yum.py
index 672451ee..1f389d30 100644
--- a/src/lib/sos/plugins/yum.py
+++ b/src/lib/sos/plugins/yum.py
@@ -22,17 +22,22 @@ class yum(sos.plugintools.PluginBase):
optionList = [("yumlist", "list repositories and packages", "slow", False)]
def checkenabled(self):
- self.files = [ "/etc/yum.conf" ]
- self.packages = [ "yum" ]
- return sos.plugintools.PluginBase.checkenabled(self)
+ if self.cInfo["policy"].pkgByName("yum") or os.path.exists("/etc/yum.conf"):
+ return True
+ return False
- def analyze(self):
+ def diagnose(self):
+ # FIXME: diagnose should only report actual problems, disabling this for now.
+ return True
# repo sanity checking
# TODO: elaborate/validate actual repo files, however this directory should
# be empty on RHEL 5+ systems.
- if self.cInfo["policy"].rhelVersion() == 5:
- if len(os.listdir("/etc/yum.repos.d/")):
- self.addAlert("/etc/yum.repos.d/ contains additional repository "+
+ try: rhelver = self.cInfo["policy"].pkgDictByName("redhat-release")[0]
+ except: rhelver = None
+
+ if rhelver == "5" or True:
+ if len(os.listdir('/etc/yum.repos.d/')):
+ self.addDiagnose("/etc/yum.repos.d/ contains additional repository "+
"information and can cause rpm conflicts.")
def setup(self):
@@ -42,7 +47,7 @@ class yum(sos.plugintools.PluginBase):
self.addCopySpec("/etc/yum.conf")
self.addCopySpec("/var/log/yum.log")
- if self.getOption("yumlist"):
+ 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
diff --git a/src/lib/sos/plugintools.py b/src/lib/sos/plugintools.py
index f9e10ae1..fc4d4b97 100644
--- a/src/lib/sos/plugintools.py
+++ b/src/lib/sos/plugintools.py
@@ -30,31 +30,11 @@ This is the base class for sosreport plugins
"""
from sos.helpers import *
from threading import Thread, activeCount
-import os, os.path, sys, string, glob, re, traceback
-import shutil
+import os, os.path, sys, string, itertools, glob, re, traceback
+import logging
from stat import *
from time import time
-# RHEL3 doesn't have a logging module, activate work-around
-try:
- import logging
-except ImportError:
- import sos.rhel3_logging
- logging = sos.rhel3_logging
-
-# python < 2.4 (RHEL3 and RHEL4) doesn't have format_exc, activate work-around
-if sys.version_info[0] <= 2 and sys.version_info[1] < 4:
- def format_exc():
- import StringIO
-
- output = StringIO.StringIO()
- traceback.print_exc(file = output)
- toret = output.getvalue()
- output.close()
- return toret
-
- traceback.format_exc = format_exc
-
class PluginBase:
"""
Base class for plugins
@@ -85,11 +65,6 @@ class PluginBase:
self.time_start = None
self.time_stop = None
- self.packages = []
- self.files = []
-
- self.must_exit = False
-
self.soslog = logging.getLogger('sos')
# get the option list into a dictionary
@@ -119,10 +94,10 @@ class PluginBase:
except KeyboardInterrupt:
raise KeyboardInterrupt
except Exception, e:
- self.soslog.log(logging.VERBOSE, "problem at path %s (%s)" % (abspath,e))
+ self.soslog.log(logging.VERBOSE, "Problem at path %s (%s)" % (abspath,e))
break
return False
-
+
def doRegexFindAll(self,regex,fname):
''' Return a list of all non overlapping matches in the string(s)
'''
@@ -134,7 +109,7 @@ class PluginBase:
for i in reg.findall(content):
out.append(i)
return out
-
+
# Methods for copying files and shelling out
def doCopyFileOrDir(self, srcpath):
# pylint: disable-msg = R0912
@@ -151,103 +126,113 @@ class PluginBase:
if copyProhibited:
return ''
- if not os.path.exists(srcpath):
- self.soslog.debug("file or directory %s does not exist" % srcpath)
- return
-
if os.path.islink(srcpath):
# This is a symlink - We need to also copy the file that it points to
-
- # FIXME: ignore directories for now
- if os.path.isdir(srcpath):
- return
-
+ # file and dir symlinks ar ehandled the same
link = os.readlink(srcpath)
- # What's the name of the symlink on the dest tree?
- dstslname = os.path.join(self.cInfo['dstroot'], srcpath.lstrip(os.path.sep))
-
if os.path.isabs(link):
# the link was an absolute path, and will not point to the new
# tree. We must adjust it.
- rpth = sosRelPath(os.path.dirname(dstslname), os.path.join(self.cInfo['dstroot'], link.lstrip(os.path.sep)))
+
+ # What's the name of the symlink on the dest tree?
+ dstslname = os.path.join(self.cInfo['dstroot'], srcpath.lstrip(os.path.sep))
+
+ # make sure the dst dir exists
+ if not (os.path.exists(os.path.dirname(dstslname)) and os.path.isdir(os.path.dirname(dstslname))):
+ # create the directory
+ os.makedirs(os.path.dirname(dstslname))
+
+ dstsldir = os.path.join(self.cInfo['dstroot'], link.lstrip(os.path.sep))
+ # Create the symlink on the dst tree
+ rpth = sosRelPath(os.path.dirname(dstslname), dstsldir)
+ os.symlink(rpth, dstslname)
else:
# no adjustment, symlink is the relative path
- rpth = link
+ dstslname = link
- # make sure the link doesn't already exists
- if os.path.exists(dstslname):
- self.soslog.log(logging.DEBUG, "skipping symlink creation: already exists (%s)" % dstslname)
+ if os.path.isdir(srcpath): # symlink to a directory
+ # FIXME: don't recurse symlinks until vicious loops are detected
return
- # make sure the dst dir exists
- if not (os.path.exists(os.path.dirname(dstslname)) and os.path.isdir(os.path.dirname(dstslname))):
- os.makedirs(os.path.dirname(dstslname))
+ abslink = os.path.abspath(os.path.dirname(srcpath) + "/" + link)
+ self.soslog.log(logging.VERBOSE2, "DIRLINK %s to %s [%s]" % (srcpath,link,abslink))
+ for tmplink in self.copiedDirs:
+ if tmplink["srcpath"] == abslink or tmplink["pointsto"] == abslink:
+ self.soslog.log(logging.VERBOSE2, "already copied [%s]" % srcpath)
+ return
- self.soslog.log(logging.VERBOSE3, "creating symlink %s -> %s" % (dstslname, rpth))
- os.symlink(rpth, dstslname)
- self.copiedFiles.append({'srcpath':srcpath, 'dstpath':rpth, 'symlink':"yes", 'pointsto':link})
- self.doCopyFileOrDir(link)
- return
+ for afile in os.listdir(srcpath):
+ if afile == '.' or afile == '..':
+ pass
+ else:
+ self.soslog.log(logging.VERBOSE2, "copying (file or dir) %s" % srcpath+'/'+afile)
+ try:
+ abspath = self.doCopyFileOrDir(srcpath+'/'+afile)
+ except SystemExit:
+ raise SystemExit
+ except KeyboardInterrupt:
+ raise KeyboardInterrupt
+ except Exception, e:
+ self.soslog.verbose(traceback.format_exc())
+
+ # if on forbidden list, abspath is null
+ if not abspath == '':
+ dstslname = sosRelPath(self.cInfo['rptdir'], abspath)
+ self.copiedDirs.append({'srcpath':srcpath, 'dstpath':dstslname, 'symlink':"yes", 'pointsto':os.path.abspath(srcpath+'/'+afile) })
+ else:
+ self.soslog.log(logging.VERBOSE2, "copying symlink %s" % srcpath)
+ try:
+ dstslname, abspath = self.__copyFile(srcpath)
+ self.copiedFiles.append({'srcpath':srcpath, 'dstpath':dstslname, 'symlink':"yes", 'pointsto':link})
+ except SystemExit:
+ raise SystemExit
+ except KeyboardInterrupt:
+ raise KeyboardInterrupt
+ except Exception, e:
+ self.soslog.log(logging.VERBOSE, "Problem at path %s (%s)" % (srcpath, e))
+
+ return abspath
else: # not a symlink
- if os.path.isdir(srcpath):
+ if not os.path.exists(srcpath):
+ self.soslog.debug("File or directory %s does not exist\n" % srcpath)
+ elif os.path.isdir(srcpath):
for afile in os.listdir(srcpath):
if afile == '.' or afile == '..':
pass
else:
self.doCopyFileOrDir(srcpath+'/'+afile)
- return
-
- # if we get here, it's definitely a regular file (not a symlink or dir)
-
- self.soslog.log(logging.VERBOSE3, "copying file %s" % srcpath)
- try:
- tdstpath, abspath = self.__copyFile(srcpath)
- except "AlreadyExists":
- self.soslog.log(logging.DEBUG, "error copying file %s (already exists)" % (srcpath))
- return
- except IOError:
- self.soslog.log(logging.VERBOSE2, "error copying file %s (IOError)" % (srcpath))
- return
- except:
- self.soslog.log(logging.VERBOSE2, "error copying file %s (SOMETHING HAPPENED)" % (srcpath))
-
- self.copiedFiles.append({'srcpath':srcpath, 'dstpath':tdstpath, 'symlink':"no"}) # save in our list
-
- return abspath
+ else:
+ # This is not a directory or a symlink
+ tdstpath, abspath = self.__copyFile(srcpath)
+ self.copiedFiles.append({'srcpath':srcpath, 'dstpath':tdstpath, 'symlink':"no"}) # save in our list
+ return abspath
def __copyFile(self, src):
""" call cp to copy a file, collect return status and output. Returns the
destination file name.
"""
- rel_dir = os.path.dirname(src).lstrip(os.path.sep)
-# if rel_dir[0] == "/": rel_dir = rel_dir[1:]
- new_dir = os.path.join(self.cInfo['dstroot'], rel_dir)
- new_fname = os.path.join(new_dir, os.path.basename(src))
-
- if not os.path.exists(new_fname):
- if not os.path.isdir(new_dir):
- os.makedirs(new_dir)
-
- if os.path.islink(src):
- linkto = os.readlink(src)
- os.symlink(linkto, new_fname)
- else:
- shutil.copy2(src, new_dir)
- else:
- raise "AlreadyExists"
-
- abspath = os.path.join(self.cInfo['dstroot'], src.lstrip(os.path.sep))
- relpath = sosRelPath(self.cInfo['rptdir'], abspath)
- return (relpath, abspath)
+ try:
+ # pylint: disable-msg = W0612
+ status, shout, runtime = sosGetCommandOutput("/bin/cp --parents -P --preserve=mode,ownership,timestamps,links " + src +" " + self.cInfo['dstroot'])
+ if status:
+ self.soslog.debug(shout)
+ abspath = os.path.join(self.cInfo['dstroot'], src.lstrip(os.path.sep))
+ relpath = sosRelPath(self.cInfo['rptdir'], abspath)
+ return relpath, abspath
+ except SystemExit:
+ raise SystemExit
+ except KeyboardInterrupt:
+ raise KeyboardInterrupt
+ except Exception,e:
+ self.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.
+ Note: do NOT use globs here.
"""
- # Glob case handling is such that a valid non-glob is a reduced glob
- for filespec in glob.glob(forbiddenPath):
- self.forbiddenPaths.append(filespec)
+ self.forbiddenPaths.append(forbiddenPath)
def getAllOptions(self):
"""
@@ -255,22 +240,14 @@ class PluginBase:
"""
return (self.optNames, self.optParms)
- def setOption(self, optionname, value):
- ''' set the named option to value.
+ def setOption(self, optionname, enable):
+ ''' enable or disable the named option.
'''
for name, parms in zip(self.optNames, self.optParms):
if name == optionname:
- parms['enabled'] = value
- return True
- else:
- return False
+ parms['enabled'] = enable
def isOptionEnabled(self, optionname):
- ''' Deprecated, use getOption() instead
- '''
- return self.getOption(optionname)
-
- def getOption(self, optionname):
''' see whether the named option is enabled.
'''
for name, parms in zip(self.optNames, self.optParms):
@@ -282,9 +259,6 @@ class PluginBase:
def addCopySpecLimit(self,fname,sizelimit = None):
"""Add a file specification (with limits)
"""
- if not ( fname and len(fname) ):
- self.soslog.warning("invalid file path")
- return False
files = glob.glob(fname)
files.sort()
cursize = 0
@@ -298,26 +272,57 @@ class PluginBase:
""" Add a file specification (can be file, dir,or shell glob) to be
copied into the sosreport by this module
"""
- if not ( copyspec and len(copyspec) ):
- self.soslog.warning("invalid file path")
- return False
# Glob case handling is such that a valid non-glob is a reduced glob
for filespec in glob.glob(copyspec):
self.copyPaths.append(filespec)
+ def copyFileGlob(self, srcglob):
+ """ Deprecated - please modify modules to use addCopySpec()
+ """
+ sys.stderr.write("Warning: thecopyFileGlob() function has been deprecated. Please")
+ sys.stderr.write("use addCopySpec() instead. Calling addCopySpec() now.")
+ self.addCopySpec(srcglob)
+
+ def copyFileOrDir(self, srcpath):
+ """ Deprecated - please modify modules to use addCopySpec()
+ """
+ sys.stderr.write("Warning: the copyFileOrDir() function has been deprecated. Please\n")
+ sys.stderr.write("use addCopySpec() instead. Calling addCopySpec() now.\n")
+ raise ValueError
+ #self.addCopySpec(srcpath)
+
+ def runExeInd(self, exe):
+ """ Deprecated - use callExtProg()
+ """
+ sys.stderr.write("Warning: the runExeInd() function has been deprecated. Please use\n")
+ sys.stderr.write("the callExtProg() function. This should only be called\n")
+ sys.stderr.write("if collect() is overridden.")
+ pass
+
def callExtProg(self, prog):
""" Execute a command independantly of the output gathering part of
sosreport
- """
+ """
+ # Log if binary is not runnable or does not exist
+ if not os.access(prog.split()[0], os.X_OK):
+ self.soslog.log(logging.VERBOSE, "binary '%s' does not exist or is not runnable" % prog.split()[0])
+
# pylint: disable-msg = W0612
- status, shout, runtime = sosGetCommandOutput(prog)
+ status, shout, runtime = sosGetCommandOutput(prog)
return status
+
+ def runExe(self, exe):
+ """ Deprecated - use collectExtOutput()
+ """
+ sys.stderr.write("Warning: the runExe() function has been deprecated. Please use\n")
+ sys.stderr.write("the collectExtOutput() function.\n")
+ pass
- def collectExtOutput(self, exe, suggest_filename = None, root_symlink = None, timeout = 300):
+ def collectExtOutput(self, exe, suggest_filename = None, root_symlink = None):
"""
Run a program and collect the output
"""
- self.collectProgs.append( (exe, suggest_filename, root_symlink, timeout) )
+ self.collectProgs.append( (exe,suggest_filename,root_symlink) )
def fileGrep(self, regexp, fname):
results = []
@@ -353,13 +358,18 @@ class PluginBase:
return outfn
- def collectOutputNow(self, exe, suggest_filename = None, root_symlink = False, timeout = 300):
+ def collectOutputNow(self, exe, suggest_filename = None, root_symlink = False):
""" Execute a command and save the output to a file for inclusion in
the report
"""
+ # First check to make sure the binary exists and is runnable.
+ if not os.access(exe.split()[0], os.X_OK):
+ self.soslog.log(logging.VERBOSE, "binary '%s' does not exist or is not runnable, trying anyways" % exe.split()[0])
+
+ # FIXME: we should have a timeout or we may end waiting forever
# pylint: disable-msg = W0612
- status, shout, runtime = sosGetCommandOutput(exe, timeout = timeout)
+ status, shout, runtime = sosGetCommandOutput(exe)
if suggest_filename:
outfn = self.makeCommandFilename(suggest_filename)
@@ -369,7 +379,7 @@ class PluginBase:
if not os.path.isdir(os.path.dirname(outfn)):
os.mkdir(os.path.dirname(outfn))
- if not (status == 127 or status == 32512): # if not command_not_found
+ if not (status == 127 or status == 32512):
outfd = open(outfn, "w")
if len(shout): outfd.write(shout+"\n")
outfd.close()
@@ -377,8 +387,7 @@ class PluginBase:
if root_symlink:
curdir = os.getcwd()
os.chdir(self.cInfo['dstroot'])
- try: os.symlink(outfn[len(self.cInfo['dstroot'])+1:], root_symlink.strip("/."))
- except: pass
+ os.symlink(outfn[len(self.cInfo['dstroot'])+1:], root_symlink.strip("/."))
os.chdir(curdir)
outfn_strip = outfn[len(self.cInfo['cmddir'])+1:]
@@ -467,10 +476,6 @@ class PluginBase:
if semaphore: semaphore.acquire()
- if self.must_exit:
- semaphore.release()
- return
-
self.soslog.log(logging.VERBOSE, "starting threaded plugin %s" % self.piName)
self.time_start = time()
@@ -481,29 +486,33 @@ class PluginBase:
try:
self.doCopyFileOrDir(path)
except SystemExit:
- if semaphore: semaphore.release()
- if threaded: return KeyboardInterrupt
- else: raise KeyboardInterrupt
+ if threaded:
+ return SystemExit
+ else:
+ raise SystemExit
except KeyboardInterrupt:
- if semaphore: semaphore.release()
- if threaded: return KeyboardInterrupt
- else: raise KeyboardInterrupt
+ if threaded:
+ return KeyboardInterrupt
+ else:
+ raise KeyboardInterrupt
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, timeout) in self.collectProgs:
+ for (prog,suggest_filename,root_symlink) in self.collectProgs:
self.soslog.debug("collecting output of '%s'" % prog)
try:
- self.collectOutputNow(prog, suggest_filename, root_symlink, timeout)
+ self.collectOutputNow(prog, suggest_filename, root_symlink)
except SystemExit:
- if semaphore: semaphore.release()
- if threaded: return SystemExit
- else: raise SystemExit
+ if threaded:
+ return SystemExit
+ else:
+ raise SystemExit
except KeyboardInterrupt:
- if semaphore: semaphore.release()
- if threaded: return KeyboardInterrupt
- else: raise KeyboardInterrupt
- except Exception, e:
+ if threaded:
+ return KeyboardInterrupt
+ else:
+ raise KeyboardInterrupt
+ except:
self.soslog.log(logging.VERBOSE2, "error collection output of '%s', traceback follows:" % prog)
self.soslog.log(logging.VERBOSE2, traceback.format_exc())
@@ -512,10 +521,6 @@ class PluginBase:
if semaphore: semaphore.release()
self.soslog.log(logging.VERBOSE, "plugin %s returning" % self.piName)
- def exit_please(self):
- """ This function tells the plugin that it should exit ASAP"""
- self.must_exit = True
-
def get_description(self):
""" This function will return the description for the plugin"""
try:
@@ -527,17 +532,7 @@ class PluginBase:
""" This function can be overidden to let the plugin decide whether
it should run or not.
"""
- # some files or packages have been specified for this package
- if len(self.files) or len(self.packages):
- for fname in self.files:
- if os.path.exists(fname):
- return True
- for pkgname in self.packages:
- if self.cInfo["policy"].pkgByName(pkgname):
- return True
- return False
-
- return True
+ return True
def defaultenabled(self):
"""This devices whether a plugin should be automatically loaded or
@@ -609,11 +604,11 @@ class PluginBase:
html = html + "<p>Commands Executed:<br><ul>\n"
# convert file name to relative path from our root
for cmd in self.executedCommands:
- if cmd["file"] and len(cmd["file"]):
- cmdOutRelPath = sosRelPath(self.cInfo['rptdir'], self.cInfo['cmddir'] + "/" + cmd['file'])
- html = html + '<li><a href="%s">%s</a></li>\n' % (cmdOutRelPath, cmd['exe'])
- else:
- html = html + '<li>%s</li>\n' % (cmd['exe'])
+ if cmd["file"] and len(cmd["file"]):
+ cmdOutRelPath = sosRelPath(self.cInfo['rptdir'], self.cInfo['cmddir'] + "/" + cmd['file'])
+ html = html + '<li><a href="%s">%s</a></li>\n' % (cmdOutRelPath, cmd['exe'])
+ else:
+ html = html + '<li>%s</li>\n' % (cmd['exe'])
html = html + "</ul></p>\n"
# Alerts
@@ -629,3 +624,5 @@ class PluginBase:
html = html + self.customText + "</p>\n"
return html
+
+
diff --git a/src/lib/sos/policyredhat.py b/src/lib/sos/policyredhat.py
index a10e7dfb..c25a9d55 100755
--- a/src/lib/sos/policyredhat.py
+++ b/src/lib/sos/policyredhat.py
@@ -26,45 +26,22 @@ from sos.helpers import *
import random
import re
import md5
-import rpm
-import time
-
-sys.path.insert(0, "/usr/share/rhn/")
-try:
- from up2date_client import up2dateAuth
- from up2date_client import config
- from rhn import rpclib
-except:
- # might fail if non-RHEL
- pass
+
+SOME_PATH = "/tmp/SomePath"
#class SosError(Exception):
# def __init__(self, code, message):
# self.code = code
# self.message = message
-#
+#
# def __str__(self):
# return 'Sos Error %s: %s' % (self.code, self.message)
-def memoized(function):
- ''' function decorator to allow caching of return values
- '''
- function.cache={}
- def f(*args):
- try:
- return function.cache[args]
- except KeyError:
- result = function.cache[args] = function(*args)
- return result
- return f
class SosPolicy:
"This class implements various policies for sos"
def __init__(self):
- self.report_file = ""
- self.report_md5 = ""
- self.reportName = ""
- self.ticketNumber = ""
+ #print "Policy init"
return
def setCommons(self, commons):
@@ -78,45 +55,35 @@ class SosPolicy:
#print "validating %s" % pluginpath
return True
- def pkgProvides(self, name):
- pkg = self.pkgByName(name)
- return pkg['providename']
-
def pkgRequires(self, name):
- pkg = self.pkgByName(name)
- return pkg['requirename']
+ # FIXME: we're relying on rpm to sort the output list
+ cmd = "/bin/rpm -q --requires %s" % (name)
+ return [requires[:-1].split() for requires in os.popen(cmd).readlines()]
def allPkgsByName(self, name):
- return self.allPkgs("name", name)
-
- def allPkgsByNameRegex(self, regex_name):
- reg = re.compile(regex_name)
- return [pkg for pkg in self.allPkgs() if reg.match(pkg['name'])]
+ # FIXME: we're relying on rpm to sort the output list
+ cmd = "/bin/rpm --qf '%%{N} %%{V} %%{R} %%{ARCH}\n' -q %s" % (name,)
+ pkgs = os.popen(cmd).readlines()
+ return [pkg[:-1].split() for pkg in pkgs if pkg.startswith(name)]
def pkgByName(self, name):
# TODO: do a full NEVRA compare and return newest version, best arch
try:
# lame attempt at locating newest
- return self.allPkgsByName(name)[-1]
- except:
- pass
- return None
-
- def allPkgs(self, ds = None, value = None):
- # if possible return the cached values
- try: return self._cache_rpm[ "%s-%s" % (ds,value) ]
- except AttributeError: self._cache_rpm = {}
- except KeyError: pass
-
- ts = rpm.TransactionSet()
- if ds and value:
- mi = ts.dbMatch(ds, value)
+ pkg = self.allPkgsByName(name)[-1]
+ except IndexError:
+ pkg = None
+
+ return pkg
+
+ def pkgDictByName(self, name):
+ # FIXME: what does this do again ??
+ pkgName = self.pkgByName(name)
+ print pkgName
+ if pkgName and len(pkgName) > len(name):
+ return pkgName[len(name)+1:].split("-")
else:
- mi = ts.dbMatch()
-
- self._cache_rpm[ "%s-%s" % (ds,value) ] = [pkg for pkg in mi]
- del mi, ts
- return self._cache_rpm[ "%s-%s" % (ds,value) ]
+ return None
def runlevelByService(self, name):
ret = []
@@ -124,7 +91,7 @@ class SosPolicy:
for tabs in commands.getoutput("/sbin/chkconfig --list %s" % name).split():
try:
(runlevel, onoff) = tabs.split(":", 1)
- except:
+ except ValueError:
pass
else:
if onoff == "on":
@@ -135,7 +102,7 @@ class SosPolicy:
def runlevelDefault(self):
try:
- reg=self.doRegexFindAll(r"^id:(\d{1}):initdefault:", "/etc/inittab")
+ reg=self.fileGrep(r"^id:(\d{1}):initdefault:", "/etc/inittab")
for initlevel in reg:
return initlevel
except:
@@ -144,36 +111,9 @@ class SosPolicy:
def kernelVersion(self):
return commands.getoutput("/bin/uname -r").strip("\n")
- def hostName(self):
- return commands.getoutput("/bin/hostname").split(".")[0]
-
- def rhelVersion(self):
- try:
- pkgname = self.pkgByName("redhat-release")["version"]
- if pkgname[0] == "4":
- return 4
- elif pkgname in [ "5Server", "5Client" ]:
- return 5
- except: pass
- return False
-
- def rhnUsername(self):
- try:
- cfg = config.initUp2dateConfig()
-
- return rpclib.xmlrpclib.loads(up2dateAuth.getSystemId())[0][0]['username']
- except:
- # ignore any exception and return an empty username
- return ""
-
def isKernelSMP(self):
- if commands.getoutput("/bin/uname -v").split()[1] == "SMP":
- return True
- else:
- return False
-
- def getArch(self):
- return commands.getoutput("/bin/uname -m").strip()
+ if self.kernelVersion()[-3:]=="smp": return True
+ else: return False
def pkgNVRA(self, pkg):
fields = pkg.split("-")
@@ -181,188 +121,85 @@ class SosPolicy:
name = "-".join(fields[:-3])
return (name, version, release, arch)
- def getDstroot(self):
- """Find a temp directory to form the root for our gathered information
- and reports.
- """
- dstroot = "/tmp/%s-%s" % (self.hostName(), time.strftime("%Y%m%d%H%M%S"))
- try:
- os.mkdir(dstroot, 0700)
- except:
- return False
- return dstroot
-
- def preWork(self):
+ def preWork(self, name="", ticket=""):
# this method will be called before the gathering begins
- localname = self.rhnUsername()
- if len(localname) == 0: localname = self.hostName()
+ localname = commands.getoutput("/bin/uname -n").split(".")[0]
- if not self.cInfo['cmdlineopts'].batch:
- try:
+ try:
+ if len(name) == 0:
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)
+ else:
+ self.reportName = str(name)
+ 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)
+ if len(self.reportName) == 0:
+ self.reportName = localname
- if len(self.reportName) == 0:
- self.reportName = localname
-
- return
+ if len(ticket) == 0:
+ self.ticketNumber = raw_input(_("Please enter the case number that you are generating this report for: "))
+ else:
+ self.ticketNumber = str(ticket)
+ self.ticketNumber = re.sub(r"[^0-9]", "", self.ticketNumber)
- 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
+ print
+ except KeyboardInterrupt:
+ print
+ sys.exit(0)
def packageResults(self):
- self.renameResults("sosreport-%s-%s.tar.bz2" % (self.reportName, time.strftime("%Y%m%d%H%M%S")))
+ if len(self.ticketNumber):
+ namestr = self.reportName + "." + self.ticketNumber
+ else:
+ namestr = self.reportName
+
+ ourtempdir = gettempdir()
+ tarballName = os.path.join(ourtempdir, "sosreport-" + namestr + ".tar.bz2")
- tarcmd = "/bin/tar -jcf %s %s" % (self.report_file, os.path.basename(self.cInfo['dstroot']))
+ namestr = namestr + "-" + str(random.randint(1, 999999))
+
+ aliasdir = os.path.join(ourtempdir, namestr)
+
+ tarcmd = "/bin/tar -jcf %s %s" % (tarballName, namestr)
print _("Creating compressed archive...")
+ if not os.access(string.split(tarcmd)[0], os.X_OK):
+ print "Unable to create tarball"
+ return
+ # FIXME: gotta be a better way...
+ os.system("/bin/mv %s %s" % (self.cInfo['dstroot'], aliasdir))
curwd = os.getcwd()
- os.chdir(os.path.dirname(self.cInfo['dstroot']))
+ os.chdir(ourtempdir)
oldmask = os.umask(077)
- status, shout = commands.getstatusoutput(tarcmd)
+ # pylint: disable-msg = W0612
+ 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']))
- return
-
- def cleanDstroot(self):
- if not os.path.isdir(os.path.join(self.cInfo['dstroot'],"sos_commands")):
- # doesn't look like a dstroot, refusing to clean
- return False
- os.system("/bin/rm -rf %s" % self.cInfo['dstroot'])
-
- def encryptResults(self):
- # make sure a report exists
- if not self.report_file:
- return False
-
- print _("Encrypting archive...")
- gpgname = self.report_file + ".gpg"
-
- try:
- keyring = self.cInfo['config'].get("general", "gpg_keyring")
- except:
- keyring = "/usr/share/sos/rhsupport.pub"
-
- try:
- recipient = self.cInfo['config'].get("general", "gpg_recipient")
- except:
- recipient = "support@redhat.com"
-
- status, output = commands.getstatusoutput("""/usr/bin/gpg --trust-model always --batch --keyring "%s" --no-default-keyring --compress-level 0 --encrypt --recipient "%s" --output "%s" "%s" """ % (keyring, recipient, gpgname, self.report_file))
- if status == 0:
- os.unlink(self.report_file)
- self.report_file = gpgname
- else:
- print _("There was a problem encrypting your report.")
- sys.exit(1)
-
- def displayResults(self):
- # make sure a report exists
- if not self.report_file:
- return False
-
- # calculate md5
- fp = open(self.report_file, "r")
- self.report_md5 = md5.new(fp.read()).hexdigest()
+ # add last 6 chars from md5sum to file name
+ fp = open(tarballName, "r")
+ md5out = md5.new(fp.read()).hexdigest()
fp.close()
-
- 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(self.report_md5 + "\n")
+ 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
print
- print _("Your sosreport has been generated and saved in:\n %s") % self.report_file
- print
- if len(self.report_md5):
- print _("The md5sum is: ") + self.report_md5
+ if md5out:
+ print _("The md5sum is: ") + md5out
print
print _("Please send this file to your support representative.")
- print
-
- def uploadResults(self):
- # make sure a report exists
- if not self.report_file:
- return False
-
- print
+ sys.stdout.write("\n")
- # make sure it's readable
- try:
- fp = open(self.report_file, "r")
- except:
- return False
-
- # read ftp URL from configuration
- try:
- upload_url = self.cInfo['config'].get("general", "upload_url")
- except:
- upload_url = "ftp://dropbox.redhat.com/incoming"
-
- from urlparse import urlparse
- url = urlparse(upload_url)
-
- if url[0] != "ftp":
- print _("Cannot upload to specified URL.")
- return
-
- # extract username and password from URL, if present
- if url[1].find("@") > 0:
- username, host = url[1].split("@", 1)
- if username.find(":") > 0:
- username, passwd = username.split(":", 1)
- else:
- passwd = None
- else:
- username, passwd, host = None, None, url[1]
-
- # extract port, if present
- if host.find(":") > 0:
- host, port = host.split(":", 1)
- port = int(port)
- else:
- port = 21
-
- path = url[2]
-
- try:
- from ftplib import FTP
- upload_name = os.path.basename(self.report_file)
-
- ftp = FTP()
- ftp.connect(host, port)
- if username and passwd:
- ftp.login(username, passwd)
- else:
- ftp.login()
- ftp.cwd(path)
- ftp.set_pasv(True)
- ftp.storbinary('STOR %s' % upload_name, fp)
- ftp.quit()
- except:
- print _("There was a problem uploading your report to Red Hat support.")
- else:
- print _("Your report was successfully uploaded to Red Hat's ftp server with name:")
- print " " + upload_name
- print
- print _("Please communicate this name to your support representative.")
- print
+ return
- fp.close()