diff options
Diffstat (limited to 'src/lib')
30 files changed, 1360 insertions, 0 deletions
diff --git a/src/lib/sos/__init__.py b/src/lib/sos/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/src/lib/sos/__init__.py diff --git a/src/lib/sos/helpers.py b/src/lib/sos/helpers.py new file mode 100755 index 00000000..447c164f --- /dev/null +++ b/src/lib/sos/helpers.py @@ -0,0 +1,140 @@ +## helpers.py +## Implement policies required for the sos system support tool + +## Copyright (C) 2006 Steve Conklin <sconklin@redhat.com> + +### This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +## Some code adapted from "Python Cookbook, 2nd ed", by Alex +## Martelli, Anna Martelli Ravenscroft, and David Ascher +## (O'Reilly Media, 2005) 0-596-00797-3 +## + +import os, popen2, fcntl, select, itertools, sys +from tempfile import mkdtemp + +workingBase = None + +def importPlugin(pluginname, name): + """ Import a plugin to extend capabilities of sosreport + """ + try: + plugin = __import__(pluginname, globals(), locals(), [name]) + except ImportError: + return None + return getattr(plugin, name) + + +def sosFindTmpDir(): + """Find a temp directory to form the root for our gathered information + and reports. + """ + workingBase = mkdtemp("","sos_") + return workingBase + + +def makeNonBlocking(fd): + """ Make the file desccriptor non-blocking. This prevents deadlocks. + """ + fl = fcntl.fcntl(fd, fcntl.F_GETFL) + try: + fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NDELAY) + except AttributeError: + fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.FNDELAY) + + +def sosGetCommandOutput(command): + """ Execute a command and gather stdin, stdout, and return status. + Adapted from Python Cookbook - O'Reilly + """ + child = popen2.Popen3(command, 1) # Capture stdout and stderr from command + child.tochild.close() # don't need to write to child's stdin + outfile = child.fromchild + outfd = outfile.fileno() + errfile = child.childerr + errfd = errfile.fileno() + makeNonBlocking(outfd) # Don't deadlock! Make fd's nonblocking. + makeNonBlocking(errfd) + outdata, errdata = [], [] + outeof = erreof = False + while True: + to_check = [outfd]*(not outeof) + [errfd]*(not erreof) + ready = select.select(to_check, [], []) # Wait for input + if outfd in ready[0]: + outchunk = outfile.read() + if outchunk == '': + outeof = True + else: + outdata.append(outchunk) + if errfd in ready[0]: + errchunk = errfile.read() + if errchunk == '': + erreof = True + else: + errdata.append(errchunk) + if outeof and erreof: + break + select.select([],[],[],.1) # Allow a little time for buffers to fill + err = child.wait() + return (err, ''.join(outdata), ''.join(errdata)) + + +# TODO - this needs to be made clean and moved to the plugin tools, so +# that it prints nice color output like sysreport +def sosStatus(stat): + """ Complete a status line that has been output to the console, + providing pass/fail indication. + """ + if not stat: + print " [ OK ]" + else: + print " [ FAILED ]" + sys.stdout.flush() + return + + +def allEqual(elements): + ''' return True if all the elements are equal, otherwise False. ''' + first_element = elements[0] + for other_element in elements[1:]: + if other_element != first_element: return False + return True + + +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 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(p1, p2, sep=os.path.sep, pardir=os.path.pardir): + ''' return a relative path from p1 equivalent to path p2. + In particular: the empty string, if p1 == p2; + p2, if p1 and p2 have no common prefix. + ''' + common, (u1, u2) = commonPrefix(p1.split(sep), p2.split(sep)) + if not common: + return p2 # leave path absolute if nothing at all in common + return sep.join( [pardir]*len(u1) + u2 ) + diff --git a/src/lib/sos/plugins/__init__.py b/src/lib/sos/plugins/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/src/lib/sos/plugins/__init__.py diff --git a/src/lib/sos/plugins/apache.py b/src/lib/sos/plugins/apache.py new file mode 100644 index 00000000..6a3e35ea --- /dev/null +++ b/src/lib/sos/plugins/apache.py @@ -0,0 +1,24 @@ +### This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class apache(sos.plugintools.PluginBase): + """This plugin gathers Apache related information + """ + def collect(self): + self.copyFileOrDir("/etc/httpd/conf/httpd.conf") + self.copyFileGlob("/etc/httpd/conf.d/*.conf") + return + diff --git a/src/lib/sos/plugins/bootloader.py b/src/lib/sos/plugins/bootloader.py new file mode 100644 index 00000000..06d653a8 --- /dev/null +++ b/src/lib/sos/plugins/bootloader.py @@ -0,0 +1,31 @@ +### This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class bootloader(sos.plugintools.PluginBase): + """This plugin gathers bootloader information + """ + def collect(self): + self.copyFileOrDir("/etc/lilo.conf") + self.copyFileOrDir("/etc/milo.conf") + self.copyFileOrDir("/etc/silo.conf") + self.copyFileOrDir("/boot/grub/grub.conf") + self.copyFileOrDir("/boot/grub/device.map") + self.copyFileOrDir("/boot/efi/elilo.conf") + self.copyFileOrDir("/boot/yaboot.conf") + + self.runExe("/sbin/lilo -q") + return + diff --git a/src/lib/sos/plugins/cluster.py b/src/lib/sos/plugins/cluster.py new file mode 100644 index 00000000..35f7e9a9 --- /dev/null +++ b/src/lib/sos/plugins/cluster.py @@ -0,0 +1,25 @@ +### This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class cluster(sos.plugintools.PluginBase): + """This plugin gathers cluster related information + """ + def collect(self): + self.copyFileOrDir("/etc/cluster.conf") + self.copyFileOrDir("/etc/cluster.xml") + self.copyFileOrDir("/etc/cluster") + return + diff --git a/src/lib/sos/plugins/filesys.py b/src/lib/sos/plugins/filesys.py new file mode 100644 index 00000000..71859047 --- /dev/null +++ b/src/lib/sos/plugins/filesys.py @@ -0,0 +1,46 @@ +### This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools +import commands + +class filesys(sos.plugintools.PluginBase): + """This plugin gathers infomraiton on filesystems + """ + def collect(self): + self.copyFileOrDir("/proc/filesystems") + self.copyFileOrDir("/etc/fstab") + self.copyFileOrDir("/proc/mounts") + self.copyFileOrDir("/proc/mdstat") + self.copyFileOrDir("/etc/raidtab") + self.copyFileOrDir("/etc/mdadm.conf") + self.copyFileOrDir("/etc/auto.master") + self.copyFileOrDir("/etc/auto.misc") + self.copyFileOrDir("/etc/auto.net") + + self.runExe("/bin/df -al") + self.runExe("/usr/sbin/lsof -b +M -n -l") + self.runExe("/bin/mount -l") + self.runExe("/sbin/blkid") + + raiddevs = commands.getoutput("/bin/cat /proc/partitions | /bin/egrep -v \"^major|^$\" | /bin/awk '{print $4}' | /bin/grep \/ | /bin/egrep -v \"p[0123456789]$\"") + disks = commands.getoutput("/bin/cat /proc/partitions | /bin/egrep -v \"^major|^$\" | /bin/awk '{print $4}' | /bin/grep -v / | /bin/egrep -v \"[0123456789]$\"") + for disk in raiddevs.split('\n'): + if '' != disk.strip(): + self.runExe("/sbin/fdisk -l /dev/%s 2>&1" % (disk,)) + for disk in disks.split('\n'): + if '' != disk.strip(): + self.runExe("/sbin/fdisk -l /dev/%s 2>&1" % (disk,)) + return + diff --git a/src/lib/sos/plugins/ftp.py b/src/lib/sos/plugins/ftp.py new file mode 100644 index 00000000..f1c80304 --- /dev/null +++ b/src/lib/sos/plugins/ftp.py @@ -0,0 +1,24 @@ +### This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class ftp(sos.plugintools.PluginBase): + """This plugin gathers FTP server related information + """ + def collect(self): + self.copyFileGlob("/etc/ftp*") + self.copyFileOrDir("/etc/vsftpd") + return + diff --git a/src/lib/sos/plugins/general.py b/src/lib/sos/plugins/general.py new file mode 100644 index 00000000..9a9544a7 --- /dev/null +++ b/src/lib/sos/plugins/general.py @@ -0,0 +1,35 @@ +### This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class general(sos.plugintools.PluginBase): + """This plugin gathers very basic system information + """ + def collect(self): + self.copyFileOrDir("/etc/redhat-release") + self.copyFileOrDir("/etc/sysconfig") + self.copyFileOrDir("/proc/stat") + self.copyFileOrDir("/var/log/dmesg") + self.copyFileOrDir("/var/log/messages") + self.copyFileOrDir("/var/log/sa") + self.copyFileOrDir("/var/log/secure") + self.copyFileOrDir("/var/log/up2date") + self.copyFileOrDir("/etc/exports") + self.copyFileGlob("/etc/cups/*.conf") + self.runExe("/bin/hostname") + self.runExe("/bin/date") + self.runExe("/usr/bin/uptime") + return + diff --git a/src/lib/sos/plugins/hardware.py b/src/lib/sos/plugins/hardware.py new file mode 100644 index 00000000..7f2b075b --- /dev/null +++ b/src/lib/sos/plugins/hardware.py @@ -0,0 +1,50 @@ +### This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools +import commands + +class hardware(sos.plugintools.PluginBase): + """This plugin gathers hardware related information + """ + def collect(self): + self.copyFileOrDir("/proc/partitions") + self.copyFileOrDir("/proc/cpuinfo") + self.copyFileOrDir("/proc/meminfo") + self.copyFileOrDir("/proc/ioports") + self.copyFileOrDir("/proc/interrupts") + self.copyFileOrDir("/proc/scsi") + self.copyFileOrDir("/proc/dma") + self.copyFileOrDir("/proc/devices") + self.copyFileOrDir("/proc/rtc") + self.copyFileOrDir("/proc/ide") + self.copyFileOrDir("/proc/bus") + self.copyFileOrDir("/etc/stinit.def") + self.copyFileOrDir("/etc/sysconfig/hwconf") + self.copyFileOrDir("/proc/chandev") + self.copyFileOrDir("/proc/dasd") + self.copyFileOrDir("/proc/s390dbf/tape") + self.runExe("/usr/share/rhn/up2dateclient/hardware.py") + self.runExe("/sbin/lspci -vvn") + self.runExe("dmesg | grep -e 'e820.' -e 'agp.'") + + for hwmodule in commands.getoutput('cat pcitable | grep -v "Card:" | awk \'{ gsub("\"","",$0); { print $NF; };} \' | uniq -u'): + cmdToRun = "dmesg | grep %s" % (hwmodule,) + self.runExe(cmdToRun) + + self.runExe("/usr/sbin/vgdisplay -vv") + self.runExe("/sbin/lsusb") + self.runExe("/usr/bin/lshal") + return + diff --git a/src/lib/sos/plugins/kernel.py b/src/lib/sos/plugins/kernel.py new file mode 100644 index 00000000..064a8314 --- /dev/null +++ b/src/lib/sos/plugins/kernel.py @@ -0,0 +1,61 @@ +### This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools +import commands, os + +class kernel(sos.plugintools.PluginBase): + """This plugin gathers kernel related information + """ + optionList = [("modinfo", 'Gathers module information on all modules', 'fast', 1), + ('sysrq', 'Trigger SysRq dumps', 'fast', 1)] + + def collect(self): + self.runExe("/bin/uname -a") + self.runExe("/sbin/lsmod") + if self.isOptionEnabled('modinfo'): + for kmod in commands.getoutput('/sbin/lsmod | /bin/cut -f1 -d" " 2>/dev/null | /bin/grep -v Module 2>/dev/null').split('\n'): + if '' != kmod.strip(): + runcmd = "/sbin/modinfo %s" % (kmod,) + self.runExe(runcmd) + self.runExe("/sbin/ksyms") + self.copyFileOrDir("/proc/filesystems") + self.copyFileOrDir("/proc/ksyms") + self.copyFileOrDir("/proc/slabinfo") + kver = commands.getoutput('/bin/uname -r') + depfile = "/lib/modules/%s/modules.dep" % (kver,) + self.copyFileOrDir(depfile) + self.copyFileOrDir("/etc/conf.modules") + self.copyFileOrDir("/etc/modules.conf") + self.copyFileOrDir("/etc/modprobe.conf") + self.runExe("/usr/sbin/dmidecode") + self.runExe("/usr/sbin/dkms status") + self.copyFileOrDir("/proc/cmdline") + self.copyFileOrDir("/proc/driver") + # trigger some sysrq's. I'm not sure I like doing it this way, but + # since we end up with the sysrq dumps in syslog whether we run the + # syslog report before or after this, I suppose I can live with it. + 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.copyFileGlob("/var/log/messages*") + + + return + diff --git a/src/lib/sos/plugins/ldap.py b/src/lib/sos/plugins/ldap.py new file mode 100644 index 00000000..4a353a26 --- /dev/null +++ b/src/lib/sos/plugins/ldap.py @@ -0,0 +1,24 @@ +### This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class ldap(sos.plugintools.PluginBase): + """This plugin gathers LDAP related information + """ + def collect(self): + self.copyFileOrDir("/etc/ldap.conf") + self.copyFileOrDir("/etc/openldap") + return + diff --git a/src/lib/sos/plugins/libraries.py b/src/lib/sos/plugins/libraries.py new file mode 100644 index 00000000..f6adf89b --- /dev/null +++ b/src/lib/sos/plugins/libraries.py @@ -0,0 +1,24 @@ +### This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class libraries(sos.plugintools.PluginBase): + """This plugin gathers information on shared libraries + """ + def collect(self): + self.copyFileOrDir("/etc/ld.so.conf") + self.copyFileOrDir("/etc/ld.so.conf.d") + return + diff --git a/src/lib/sos/plugins/mail.py b/src/lib/sos/plugins/mail.py new file mode 100644 index 00000000..8945550d --- /dev/null +++ b/src/lib/sos/plugins/mail.py @@ -0,0 +1,25 @@ +### This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class mail(sos.plugintools.PluginBase): + """This plugin gathers mail server related information + """ + def collect(self): + self.copyFileOrDir("/etc/mail") + self.copyFileOrDir("/etc/postfix/main.cf") + self.copyFileOrDir("/etc/postfix/master.cf") + return + diff --git a/src/lib/sos/plugins/memory.py b/src/lib/sos/plugins/memory.py new file mode 100644 index 00000000..0e6d6a60 --- /dev/null +++ b/src/lib/sos/plugins/memory.py @@ -0,0 +1,27 @@ +### This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class memory(sos.plugintools.PluginBase): + """This plugin gathers memory usage information + """ + def collect(self): + self.copyFileOrDir("/proc/pci") + self.copyFileOrDir("/proc/meminfo") + + self.runExe("/bin/dmesg | grep -e 'e820.' -e 'aperature.'") + self.runExe("/usr/bin/free") + return + diff --git a/src/lib/sos/plugins/named.py b/src/lib/sos/plugins/named.py new file mode 100644 index 00000000..7d77c40d --- /dev/null +++ b/src/lib/sos/plugins/named.py @@ -0,0 +1,34 @@ +### This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools +import commands +import os + +class named(sos.plugintools.PluginBase): + """This plugin gathers named related information + """ + def collect(self): + dnsdir = "" + self.copyFileOrDir("/etc/named.boot") + self.copyFileOrDir("/etc/named.conf") + 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(): + print "FIX named.py - hangs when named chrooted because of /var/named/chroot/proc" + #self.copyFileOrDir(dnsdir) + return + diff --git a/src/lib/sos/plugins/networking.py b/src/lib/sos/plugins/networking.py new file mode 100644 index 00000000..f6a8fdb0 --- /dev/null +++ b/src/lib/sos/plugins/networking.py @@ -0,0 +1,58 @@ +### This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools +import os,re + +class networking(sos.plugintools.PluginBase): + """This plugin gathers network related information + """ + + def get_interface_name(self,ifconfigFile): + """Return a dictionnary for wich key are intefrace name according to the + output of ifcongif-a stored in 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 collect(self): + self.copyFileOrDir("/etc/nsswitch.conf") + self.copyFileOrDir("/etc/yp.conf") + self.copyFileOrDir("/etc/inetd.conf") + self.copyFileOrDir("/etc/xinetd.conf") + self.copyFileOrDir("/etc/xinetd.d") + self.copyFileGlob("/etc/host*") + self.copyFileOrDir("/etc/resolv.conf") + # self.copyFileOrDir("/etc/sysconfig/iptables-config") + # The above is redundant + ifconfigFile=self.runExe("/sbin/ifconfig -a") + self.runExe("/sbin/route -n") + self.runExe("/sbin/ipchains -nvL") + self.runExe("/sbin/iptables -t filter -nvL") + self.runExe("/sbin/iptables -t nat -nvL") + self.runExe("/sbin/iptables -t mangle -nvL") + if ifconfigFile: + for eth in self.get_interface_name(ifconfigFile): + self.runExe("/sbin/ethtool "+eth) + + return + diff --git a/src/lib/sos/plugins/pam.py b/src/lib/sos/plugins/pam.py new file mode 100644 index 00000000..adce0046 --- /dev/null +++ b/src/lib/sos/plugins/pam.py @@ -0,0 +1,23 @@ +### This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class pam(sos.plugintools.PluginBase): + """This plugin gathers PAM related information + """ + def collect(self): + self.copyFileOrDir("/etc/pam.d") + return + diff --git a/src/lib/sos/plugins/process.py b/src/lib/sos/plugins/process.py new file mode 100644 index 00000000..d360af10 --- /dev/null +++ b/src/lib/sos/plugins/process.py @@ -0,0 +1,24 @@ +### This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class process(sos.plugintools.PluginBase): + """This plugin gathers process information + """ + def collect(self): + self.runExe("/bin/ps auxww") + self.runExe("/usr/bin/pstree") + return + diff --git a/src/lib/sos/plugins/rhn.py b/src/lib/sos/plugins/rhn.py new file mode 100644 index 00000000..512e0d7d --- /dev/null +++ b/src/lib/sos/plugins/rhn.py @@ -0,0 +1,86 @@ +### This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +from sos.plugintools import PluginBase + +class rhn(PluginBase): + """This plugin gathers RHN server related information + """ + def collect(self): + # XXX check for the presence of requisite packages + satellite = self.cInfo["policy"].pkgByName("rhns-satellite-tools") + proxy = self.cInfo["policy"].pkgByName("rhns-proxy-tools") + if not satellite and not proxy: + return + + # + # First, grab things needed from both Satellite and Proxy systems + # + # TODO: add chain load so we can use existing modules for httpd, &c. + # + + # basic RHN logs and configs + self.copyFileGlob("/var/log/rhn*") + self.copyFileOrDir("/etc/rhn") + self.runExe("/usr/share/rhn/up2date_client/hardware.py") + + # httpd + self.copyFileOrDir("/etc/httpd/conf") + self.copyFileOrDir("/var/log/httpd") + + # RPM manifests + self.runExe("/bin/rpm -qa --last | sort") + + # monitoring scout logs + self.copyFileGlob("/home/nocpulse/var/*.log*") + self.copyFileGlob("/home/nocpulse/var/commands/*.log*") + + # + # Now, go for product-specific data + # + if satellite: + self.collectSatellite(satellite) + + if proxy: + self.collectProxy(proxy) + + def collectSatellite(self, satellite): + self.runExe("/usr/bin/rhn-schema-version") + self.runExe("/usr/bin/rhn-charsets") + + # oracle + self.copyFileOrDir("/etc/tnsnames.ora") + + # tomcat (4.x and newer satellites only) + if not self.cInfo["policy"].pkgNVRA(satellite)[1].startswith("3."): + self.copyFileOrDir("/etc/tomcat5") + self.copyFileOrDir("/var/log/tomcat5") + + # jabberd + # - logs to /var/log/messages + self.copyFileOrDir("/etc/jabberd") + + # SSL build + self.copyFileOrDir("/root/ssl-build") + + # monitoring logs + self.copyFileGlob("/opt/notification/var/*.log*") + self.copyFileGlob("/var/tmp/ack_handler.log*") + self.copyFileGlob("/var/tmp/enqueue.log*") + + def collectProxy(self, proxy): + # squid + self.copyFileOrDir("/etc/squid") + self.copyFileOrDir("/var/log/squid") + diff --git a/src/lib/sos/plugins/rpm.py b/src/lib/sos/plugins/rpm.py new file mode 100644 index 00000000..44b9d5c8 --- /dev/null +++ b/src/lib/sos/plugins/rpm.py @@ -0,0 +1,32 @@ +### This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class rpm(sos.plugintools.PluginBase): + """This plugin gathers RPM information + """ + optionList = [("rpmq", "Queries for package information via rpm -q", "fast", 1), + ("rpmva", "Runs a verify on all packages", "slow", 0)] + + def collect(self): + self.copyFileOrDir("/var/log/rpmpkgs") + + if self.isOptionEnabled("rpmq"): + self.runExe("/bin/rpm -qa --qf \"%{NAME}-%{VERSION}-%{RELEASE}-%{ARCH}\n\"") + + if self.isOptionEnabled("rpmva"): + self.runExe("/bin/rpm -Va") + return + diff --git a/src/lib/sos/plugins/samba.py b/src/lib/sos/plugins/samba.py new file mode 100644 index 00000000..848da265 --- /dev/null +++ b/src/lib/sos/plugins/samba.py @@ -0,0 +1,25 @@ +### This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class samba(sos.plugintools.PluginBase): + """This plugin gathers Samba related information + """ + def collect(self): + self.copyFileOrDir("/etc/samba") + self.runExe("/usr/bin/wbinfo -g") + self.runExe("/usr/bin/wbinfo -u") + return + diff --git a/src/lib/sos/plugins/selinux.py b/src/lib/sos/plugins/selinux.py new file mode 100644 index 00000000..51fe90d9 --- /dev/null +++ b/src/lib/sos/plugins/selinux.py @@ -0,0 +1,26 @@ +### This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class selinux(sos.plugintools.PluginBase): + """This plugin gathers selinux related information + """ + def collect(self): + self.runExe("/usr/bin/selinuxconfig") + self.runExe("/usr/sbin/sestatus") + self.runExe("/bin/rpm -q -V selinux-policy-targeted") + self.runExe("/bin/rpm -q -V selinux-policy-strict") + return + diff --git a/src/lib/sos/plugins/squid.py b/src/lib/sos/plugins/squid.py new file mode 100644 index 00000000..e552a99e --- /dev/null +++ b/src/lib/sos/plugins/squid.py @@ -0,0 +1,23 @@ +### This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class squid(sos.plugintools.PluginBase): + """This plugin gathers Squid related information + """ + def collect(self): + self.copyFileOrDir("/etc/squid/squid.conf") + return + diff --git a/src/lib/sos/plugins/startup.py b/src/lib/sos/plugins/startup.py new file mode 100644 index 00000000..820ee0e7 --- /dev/null +++ b/src/lib/sos/plugins/startup.py @@ -0,0 +1,26 @@ +### This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class startup(sos.plugintools.PluginBase): + """This plugin gathers startup information + """ + def collect(self): + self.copyFileOrDir("/etc/rc.d") + + self.runExe("/sbin/chkconfig --list") + # self.runExe("/bin/ls /etc/rc.d/rc*.d/") # This is redundant. + return + diff --git a/src/lib/sos/plugins/system.py b/src/lib/sos/plugins/system.py new file mode 100644 index 00000000..b98b40df --- /dev/null +++ b/src/lib/sos/plugins/system.py @@ -0,0 +1,31 @@ +### This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class system(sos.plugintools.PluginBase): + """This plugin gathers core system related information + """ + def collect(self): + self.copyFileOrDir("/proc/sys") + self.copyFileOrDir("/etc/sysctl.conf") + self.copyFileGlob("/etc/cron*") + self.copyFileOrDir("/etc/syslog.conf") + self.copyFileOrDir("/etc/ntp.conf") + self.copyFileOrDir("/etc/ntp/step-tickers") + self.copyFileOrDir("/etc/ntp/ntpservers") + self.copyFileOrDir("/etc/auto.*") + + return + diff --git a/src/lib/sos/plugins/tarball.py b/src/lib/sos/plugins/tarball.py new file mode 100644 index 00000000..787ffed2 --- /dev/null +++ b/src/lib/sos/plugins/tarball.py @@ -0,0 +1,41 @@ +### This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sys +import sos.plugintools +from sos.helpers import * + +class tarball(sos.plugintools.PluginBase): + """This plugin tars up the information gathered by sosreport + """ + def postproc(self, dstroot): + 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] + + dirName = name + "." + ticketNumber + self.runExeInd("/bin/mkdir /tmp/%s" % dirName) + self.runExeInd("/bin/mv %s/* /tmp/%s" + % (dstroot, dirName)) + self.runExeInd("/bin/rm -rf %s" % dstroot) + self.runExeInd("/bin/tar --directory /tmp -jcf " + "/tmp/%s.tar.bz2 %s" + % (dirName, dirName)) + self.runExeInd("/bin/rm -rf /tmp/%s" % dirName) + print "Your tarball is located at /tmp/%s.tar.bz2" % dirName + return "/tmp/" + dirName + diff --git a/src/lib/sos/plugins/x11.py b/src/lib/sos/plugins/x11.py new file mode 100644 index 00000000..9d9b27c9 --- /dev/null +++ b/src/lib/sos/plugins/x11.py @@ -0,0 +1,26 @@ +### This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class x11(sos.plugintools.PluginBase): + """This plugin gathers X related information + """ + def collect(self): + self.copyFileOrDir("/etc/X11") + self.copyFileGlob("/var/log/Xorg.*.log") + self.copyFileGlob("/var/log/XFree86.*.log") + self.runExe("/bin/dmesg | grep -e 'agpgart.'") + return + diff --git a/src/lib/sos/plugintools.py b/src/lib/sos/plugintools.py new file mode 100644 index 00000000..1a0fd9d4 --- /dev/null +++ b/src/lib/sos/plugintools.py @@ -0,0 +1,299 @@ +## plugintools.py +## This exports methods available for use by plugins for sos + +## Copyright (C) 2006 Steve Conklin <sconklin@redhat.com> + +### This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +from sos.helpers import * +import os, os.path, sys, string, itertools, glob + +class PluginBase: + """ + Base class for plugins + """ +# optionList = [] +# copiedFiles = [] +# copiedDirs = [] +# executedCommands = [] +# alerts = [] +# customText = "" +# cInfo = None +# piName = None +# optNames = [] +# optParms = [] + + def __init__(self, pluginname, commons): + try: + foo = len(self.optionList) + except: + self.optionList = [] + self.copiedFiles = [] + self.copiedDirs = [] + self.executedCommands = [] + self.alerts = [] + self.customText = "" + self.optNames = [] + self.optParms = [] + self.piName = pluginname + self.cInfo = commons + + # get the option list into a dictionary + for opt in self.optionList: + self.optNames.append(opt[0]) + self.optParms.append({'desc':opt[1], 'speed':opt[2], 'enabled':opt[3]}) + return + + + def __copyFile(self, src): + """ call cp to copy a file, collect return status and output. Returns the + destination file name. + """ + print "Copying %s" % src, + sys.stdout.flush() + + status, shout, sherr = sosGetCommandOutput("/bin/cp --parents " + src + " " + self.cInfo['dstroot']) + self.cInfo['logfd'].write(shout) + self.cInfo['logfd'].write(sherr) + sosStatus(status) + abspath = os.path.join(self.cInfo['dstroot'], src.lstrip(os.path.sep)) + relpath = sosRelPath(self.cInfo['rptdir'], abspath) + return relpath, abspath + + + def __copyDir(self, src): + """ call cp to copy a directory tree, collect return status and output. Returns the path where it + got put. + """ + print "Copying %s" % src, + sys.stdout.flush() + + status, shout, sherr = sosGetCommandOutput("/bin/cp --parents -R " + src + " " + self.cInfo['dstroot']) + self.cInfo['logfd'].write(shout) + self.cInfo['logfd'].write(sherr) + sosStatus(status) + abspath = self.cInfo['dstroot'] + src + relpath = sosRelPath(self.cInfo['rptdir'], abspath) + return relpath, abspath + + # Methods for dealing with options + + def getAllOptions(self): + return (self.optNames, self.optParms) + + 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'] = enable + + def isOptionEnabled(self, optionname): + ''' see whether the named option is enabled. + ''' + for name, parms in zip(self.optNames, self.optParms): + if name == optionname: + return parms['enabled'] + # nonexistent options aren't enabled. + return 0 + + def copyFileGlob(self, srcglob): + ''' Copy all files and/or directories specified by the glob to the + destination tree. + ''' + for source in glob.glob(srcglob): + self.copyFileOrDir(source) + + # Methods for copying files and shelling out + def copyFileOrDir(self, srcpath): + ''' Copy file or directory to the destination tree. If a directory, then everything + below it is recursively copied. A list of copied files are saved for use later + in preparing a report + ''' + if os.path.islink(srcpath): + # This is a symlink - We need to also copy the file that it points to + # file and dir symlinks ar ehandled the same + link = os.readlink(srcpath) + if os.path.isabs(link): + # the link was an absolute path, and will not point to the new + # tree. We must adjust it. + + # 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) + + if os.path.isdir(srcpath): + dstslname, abspath = self.__copyDir(srcpath) + self.copiedDirs.append({'srcpath':srcpath, 'dstpath':dstslname, 'symlink':"yes", 'pointsto':link}) + else: + dstslname, abspath = self.__copyFile(srcpath) + self.copiedFiles.append({'srcpath':srcpath, 'dstpath':dstslname, 'symlink':"yes", 'pointsto':link}) + + # Recurse to copy whatever it points to + newpath = os.path.normpath(os.path.join(os.path.dirname(srcpath), link)) + self.copyFileOrDir(newpath) + return abspath + + else: + if not os.path.exists(srcpath): + self.cInfo['logfd'].write("File or directory %s does not exist\n" % srcpath) + elif os.path.isdir(srcpath): + tdstpath, abspath = self.__copyDir(srcpath) + self.copiedDirs.append({'srcpath':srcpath, 'dstpath':tdstpath, 'symlink':"no", 'pointsto':""}) + 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 runExeInd(self, exe): + """ Execute a command independantly of the output gathering part of + sosreport + """ + + # First check to make sure the binary exists and is runnable. + if not os.access(exe.split()[0], os.X_OK): + return + + status, shout, sherr = sosGetCommandOutput(exe) + + return status + + def runExe(self, exe): + """ 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): + return + + print "Collecting output from command <%s>" % (exe), + sys.stdout.flush() + + status, shout, sherr = sosGetCommandOutput(exe) + + # build file name for output + rawcmd = os.path.basename(exe).strip()[:28] + + # Mangle command to make it suitable for a file name + tabl = string.maketrans(" /\t;#$|%\"'`}{\n", "_._-----------") + mangledname = rawcmd.translate(tabl) + + outfn = self.cInfo['cmddir'] + "/" + self.piName + "." + mangledname + + # check for collisions + while os.path.exists(outfn): + outfn = outfn + "z" + + outfd = open(outfn, "w") + outfd.write(shout) + outfd.close() + self.cInfo['logfd'].write(sherr) + sosStatus(status) + # save info for later + self.executedCommands.append({'exe': exe, 'file':outfn}) # save in our list + return outfn + + # For adding output + def addAlert(self, alertstring): + """ Add an alert to the collection of alerts for this plugin. These + will be displayed in the report + """ + self.alerts.append(alertstring) + return + + + def addCustomText(self, text): + """ Append text to the custom text that is included in the report. This + is freeform and can include html. + """ + self.customText = self.customText + text + return + + + # What follows are the methods which may be overridden by the plugin + + + def collect(self): + pass + + def analyze(self): + pass + + def postproc(self, dstroot): + pass + + def report(self): + """ Present all information that was gathered in an html file that allows browsing + the results. + """ + # TODO make this prettier, this is a first pass + html = '<hr/><a name="%s"></a>\n' % self.piName + + # Intro + html = html + "<h2> Plugin <em>" + self.piName + "</em></h2>\n" + + # Files + if len(self.copiedFiles): + html = html + "<p>Files copied:<br><ul>\n" + for file in self.copiedFiles: + html = html + '<li><a href="%s">%s</a>' % (file['dstpath'], file['srcpath']) + if (file['symlink'] == "yes"): + html = html + " (symlink to %s)" % file['pointsto'] + html = html + '</li>\n' + html = html + "</ul></p>\n" + + # Dirs + if len(self.copiedDirs): + html = html + "<p>Directories Copied:<br><ul>\n" + for dir in self.copiedDirs: + html = html + '<li><a href="%s">%s</a>\n' % (dir['dstpath'], dir['srcpath']) + if (dir['symlink'] == "yes"): + html = html + " (symlink to %s)" % dir['pointsto'] + html = html + '</li>\n' + html = html + "</ul></p>\n" + + # Command Output + if len(self.executedCommands): + html = html + "<p>Commands Executed:<br><ul>\n" + for cmd in self.executedCommands: + html = html + '<li><a href="%s">%s</a></li>\n' % (cmd['file'], cmd['exe']) + html = html + "</ul></p>\n" + + # Alerts + if len(self.alerts): + html = html + "<p>Alerts:<br><ul>\n" + for alert in self.alerts: + html = html + '<li>%s</li>\n' % alert + html = html + "</ul></p>\n" + + # Custom Text + if (self.customText != ""): + html = html + "<p>Additional Information:<br>\n" + html = html + self.customText + "</p>\n" + + return html + + diff --git a/src/lib/sos/policyredhat.py b/src/lib/sos/policyredhat.py new file mode 100755 index 00000000..14e5fa8a --- /dev/null +++ b/src/lib/sos/policyredhat.py @@ -0,0 +1,70 @@ +## policy-redhat.py +## Implement policies required for the sos system support tool + +## Copyright (C) Steve Conklin <sconklin@redhat.com> + +### This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +#import os.path +#import copy +#import md5 +import os + +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) + + +class SosPolicy: + "This class implements various policies for sos" + def __init__(self): + #print "Policy init" + return + + def validatePlugin(self, pluginpath): + "Validates the plugin as being acceptable to run" + # return value + # TODO implement this + #print "validating %s" % pluginpath + return True + + def allPkgsByName(self, 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] 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 + pkg = self.allPkgsByName(name)[-1] + except IndexError: + pkg = None + + return pkg + + def pkgNVRA(self, pkg): + fields = pkg.split("-") + version, release, arch = fields[-3:] + name = "-".join(fields[:-3]) + return (name, version, release, arch) + |