diff options
Diffstat (limited to 'src')
31 files changed, 379 insertions, 303 deletions
diff --git a/src/example_plugins/example.py b/src/example_plugins/example.py index 98c40a5d..1e650417 100755 --- a/src/example_plugins/example.py +++ b/src/example_plugins/example.py @@ -38,7 +38,7 @@ class example(sos.plugintools.PluginBase): ('follicles', 'Gathers information about each follicle on every toe', 'slow', 0), ('color', 'Gathers toenail polish color', 'fast', 0)] - def collect(self): + def setup(self): ''' First phase - Collect all the information we need. Directories are copied recursively. arbitrary commands may be executed using the susRunExe method. Information is automatically saved, and @@ -46,16 +46,18 @@ class example(sos.plugintools.PluginBase): copied to the saved tree. Also, links are provided to the output from each command. ''' # Here's how to copy files and directory trees - self.copyFileOrDir("/etc/hosts") + self.addCopySpec("/etc/hosts") # this one saves a file path to the copy for later analysis - self.fooFilePath = self.copyFileOrDir("/proc/cpuinfo") + # FIXME: Need to figure out how to do this + # self.fooFilePath = self.copyFileOrDir("/proc/cpuinfo") # Here's how to test your options and execute if enabled if self.isOptionEnabled("init.d"): - self.copyFileOrDir("/etc/init.d") # copies a whole directory tree + self.addCopySpec("/etc/init.d") # copies a whole directory tree # Here's how to execute a command # you can save the path to the copied file for later analysis if desired + # FIXME: Need to figure out how to do this self.psCmdDstFileName = self.runExe("/bin/ps -ef") return diff --git a/src/example_plugins/fsusage.py b/src/example_plugins/fsusage.py index 898aaa12..2532c5f7 100644 --- a/src/example_plugins/fsusage.py +++ b/src/example_plugins/fsusage.py @@ -18,6 +18,6 @@ import sos.plugintools # Class name must be the same as file name and method names must not change class fsusage(sos.plugintools.PluginBase): - def collect(self): - self.psCmdDstFileName = self.runExe("/bin/df -al") + def setup(self): + self.psCmdDstFileName = self.collectExtOutput("/bin/df -al") return diff --git a/src/example_plugins/release.py b/src/example_plugins/release.py index 5df7ada1..db4d7581 100644 --- a/src/example_plugins/release.py +++ b/src/example_plugins/release.py @@ -16,6 +16,6 @@ import sos.plugintools # Class name must be the same as file name and method names must not change class release(sos.plugintools.PluginBase): - def collect(self): - self.copyFileOrDir("/etc/redhat-release") + def setup(self): + self.addCopySpec("/etc/redhat-release") return diff --git a/src/example_plugins/runcommand.py b/src/example_plugins/runcommand.py index af8cc4fe..df8951d2 100755 --- a/src/example_plugins/runcommand.py +++ b/src/example_plugins/runcommand.py @@ -35,10 +35,10 @@ class runcommand(sos.plugintools.PluginBase): Your finished plugin should be included with your package and installed in python's site-packages/sos/plugins/ directory """ - def collect(self): + def setup(self): ''' Run a command. Output is automatically included in the report. ''' - self.runExe("/path/to/my/script --myoption --anotheroption") + self.collectExtOutput("/path/to/my/script --myoption --anotheroption") # if (for example) that command created files /foo/bar/baz.txt and # we want to include that in our report, we include the next line: diff --git a/src/lib/sos/plugins/apache.py b/src/lib/sos/plugins/apache.py index 6a3e35ea..81a91c55 100644 --- a/src/lib/sos/plugins/apache.py +++ b/src/lib/sos/plugins/apache.py @@ -13,12 +13,13 @@ ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. import sos.plugintools +from threading import Thread 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") + def setup(self): + self.addCopySpec("/etc/httpd/conf/httpd.conf") + self.addCopySpec("/etc/httpd/conf.d/*.conf") return diff --git a/src/lib/sos/plugins/bootloader.py b/src/lib/sos/plugins/bootloader.py index 06d653a8..f171917f 100644 --- a/src/lib/sos/plugins/bootloader.py +++ b/src/lib/sos/plugins/bootloader.py @@ -17,15 +17,15 @@ 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") + def setup(self): + self.addCopySpec("/etc/lilo.conf") + self.addCopySpec("/etc/milo.conf") + self.addCopySpec("/etc/silo.conf") + self.addCopySpec("/boot/grub/grub.conf") + self.addCopySpec("/boot/grub/device.map") + self.addCopySpec("/boot/efi/elilo.conf") + self.addCopySpec("/boot/yaboot.conf") - self.runExe("/sbin/lilo -q") + self.collectExtOutput("/sbin/lilo -q") return diff --git a/src/lib/sos/plugins/cluster.py b/src/lib/sos/plugins/cluster.py index 35f7e9a9..eaa173f9 100644 --- a/src/lib/sos/plugins/cluster.py +++ b/src/lib/sos/plugins/cluster.py @@ -17,9 +17,9 @@ 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") + def setup(self): + self.addCopySpec("/etc/cluster.conf") + self.addCopySpec("/etc/cluster.xml") + self.addCopySpec("/etc/cluster") return diff --git a/src/lib/sos/plugins/filesys.py b/src/lib/sos/plugins/filesys.py index 71859047..9e507423 100644 --- a/src/lib/sos/plugins/filesys.py +++ b/src/lib/sos/plugins/filesys.py @@ -18,29 +18,29 @@ 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") + def setup(self): + self.addCopySpec("/proc/filesystems") + self.addCopySpec("/etc/fstab") + self.addCopySpec("/proc/mounts") + self.addCopySpec("/proc/mdstat") + self.addCopySpec("/etc/raidtab") + self.addCopySpec("/etc/mdadm.conf") + self.addCopySpec("/etc/auto.master") + self.addCopySpec("/etc/auto.misc") + self.addCopySpec("/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") + self.collectExtOutput("/bin/df -al") + self.collectExtOutput("/usr/sbin/lsof -b +M -n -l") + self.collectExtOutput("/bin/mount -l") + self.collectExtOutput("/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,)) + self.collectExtOutput("/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,)) + self.collectExtOutput("/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 index f1c80304..54a50669 100644 --- a/src/lib/sos/plugins/ftp.py +++ b/src/lib/sos/plugins/ftp.py @@ -17,8 +17,8 @@ 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") + def setup(self): + self.addCopySpec("/etc/ftp*") + self.addCopySpec("/etc/vsftpd") return diff --git a/src/lib/sos/plugins/general.py b/src/lib/sos/plugins/general.py index 9a9544a7..7488cc2c 100644 --- a/src/lib/sos/plugins/general.py +++ b/src/lib/sos/plugins/general.py @@ -17,19 +17,19 @@ 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") + def setup(self): + self.addCopySpec("/etc/redhat-release") + self.addCopySpec("/etc/sysconfig") + self.addCopySpec("/proc/stat") + self.addCopySpec("/var/log/dmesg") + self.addCopySpec("/var/log/messages") + self.addCopySpec("/var/log/sa") + self.addCopySpec("/var/log/secure") + self.addCopySpec("/var/log/up2date") + self.addCopySpec("/etc/exports") + self.addCopySpec("/etc/cups/*.conf") + self.collectExtOutput("/bin/hostname") + self.collectExtOutput("/bin/date") + self.collectExtOutput("/usr/bin/uptime") return diff --git a/src/lib/sos/plugins/hardware.py b/src/lib/sos/plugins/hardware.py index 7f2b075b..73f51b93 100644 --- a/src/lib/sos/plugins/hardware.py +++ b/src/lib/sos/plugins/hardware.py @@ -18,33 +18,33 @@ 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.'") + def setup(self): + self.addCopySpec("/proc/partitions") + self.addCopySpec("/proc/cpuinfo") + self.addCopySpec("/proc/meminfo") + self.addCopySpec("/proc/ioports") + self.addCopySpec("/proc/interrupts") + self.addCopySpec("/proc/scsi") + self.addCopySpec("/proc/dma") + self.addCopySpec("/proc/devices") + self.addCopySpec("/proc/rtc") + self.addCopySpec("/proc/ide") + self.addCopySpec("/proc/bus") + self.addCopySpec("/etc/stinit.def") + self.addCopySpec("/etc/sysconfig/hwconf") + self.addCopySpec("/proc/chandev") + self.addCopySpec("/proc/dasd") + self.addCopySpec("/proc/s390dbf/tape") + self.collectExtOutput("/usr/share/rhn/up2dateclient/hardware.py") + self.collectExtOutput("/sbin/lspci -vvn") + self.collectExtOutput("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.collectExtOutput(cmdToRun) - self.runExe("/usr/sbin/vgdisplay -vv") - self.runExe("/sbin/lsusb") - self.runExe("/usr/bin/lshal") + self.collectExtOutput("/usr/sbin/vgdisplay -vv") + self.collectExtOutput("/sbin/lsusb") + self.collectExtOutput("/usr/bin/lshal") return diff --git a/src/lib/sos/plugins/kernel.py b/src/lib/sos/plugins/kernel.py index 064a8314..56f186c1 100644 --- a/src/lib/sos/plugins/kernel.py +++ b/src/lib/sos/plugins/kernel.py @@ -21,28 +21,28 @@ class kernel(sos.plugintools.PluginBase): 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") + def setup(self): + self.collectExtOutput("/bin/uname -a") + self.collectExtOutput("/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") + self.collectExtOutput(runcmd) + self.collectExtOutput("/sbin/ksyms") + self.addCopySpec("/proc/filesystems") + self.addCopySpec("/proc/ksyms") + self.addCopySpec("/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") + self.addCopySpec(depfile) + self.addCopySpec("/etc/conf.modules") + self.addCopySpec("/etc/modules.conf") + self.addCopySpec("/etc/modprobe.conf") + self.collectExtOutput("/usr/sbin/dmidecode") + self.collectExtOutput("/usr/sbin/dkms status") + self.addCopySpec("/proc/cmdline") + self.addCopySpec("/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. @@ -54,7 +54,7 @@ class kernel(sos.plugintools.PluginBase): commands.getoutput("/bin/echo %s > /proc/sys/kernel/sysrq" % (sysrq_state,)) # No need to grab syslog here if we can't trigger sysrq, so keep this # inside the if - self.copyFileGlob("/var/log/messages*") + self.addCopySpec("/var/log/messages*") return diff --git a/src/lib/sos/plugins/ldap.py b/src/lib/sos/plugins/ldap.py index 4a353a26..c2efd52a 100644 --- a/src/lib/sos/plugins/ldap.py +++ b/src/lib/sos/plugins/ldap.py @@ -17,8 +17,8 @@ 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") + def setup(self): + self.addCopySpec("/etc/ldap.conf") + self.addCopySpec("/etc/openldap") return diff --git a/src/lib/sos/plugins/libraries.py b/src/lib/sos/plugins/libraries.py index f6adf89b..1ce7b590 100644 --- a/src/lib/sos/plugins/libraries.py +++ b/src/lib/sos/plugins/libraries.py @@ -17,8 +17,8 @@ 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") + def setup(self): + self.addCopySpec("/etc/ld.so.conf") + self.addCopySpec("/etc/ld.so.conf.d") return diff --git a/src/lib/sos/plugins/mail.py b/src/lib/sos/plugins/mail.py index 8945550d..0f38acf2 100644 --- a/src/lib/sos/plugins/mail.py +++ b/src/lib/sos/plugins/mail.py @@ -17,9 +17,9 @@ 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") + def setup(self): + self.addCopySpec("/etc/mail") + self.addCopySpec("/etc/postfix/main.cf") + self.addCopySpec("/etc/postfix/master.cf") return diff --git a/src/lib/sos/plugins/memory.py b/src/lib/sos/plugins/memory.py index 0e6d6a60..688b7011 100644 --- a/src/lib/sos/plugins/memory.py +++ b/src/lib/sos/plugins/memory.py @@ -17,11 +17,11 @@ 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") + def setup(self): + self.addCopySpec("/proc/pci") + self.addCopySpec("/proc/meminfo") - self.runExe("/bin/dmesg | grep -e 'e820.' -e 'aperature.'") - self.runExe("/usr/bin/free") + self.collectExtOutput("/bin/dmesg | grep -e 'e820.' -e 'aperature.'") + self.collectExtOutput("/usr/bin/free") return diff --git a/src/lib/sos/plugins/named.py b/src/lib/sos/plugins/named.py index 7d77c40d..3178bbe1 100644 --- a/src/lib/sos/plugins/named.py +++ b/src/lib/sos/plugins/named.py @@ -19,16 +19,17 @@ import os class named(sos.plugintools.PluginBase): """This plugin gathers named related information """ - def collect(self): + def setup(self): dnsdir = "" - self.copyFileOrDir("/etc/named.boot") - self.copyFileOrDir("/etc/named.conf") + self.addCopySpec("/etc/named.boot") + self.addCopySpec("/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) + 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 f6a8fdb0..5eecb12b 100644 --- a/src/lib/sos/plugins/networking.py +++ b/src/lib/sos/plugins/networking.py @@ -34,25 +34,25 @@ class networking(sos.plugintools.PluginBase): 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") + def setup(self): + self.addCopySpec("/etc/nsswitch.conf") + self.addCopySpec("/etc/yp.conf") + self.addCopySpec("/etc/inetd.conf") + self.addCopySpec("/etc/xinetd.conf") + self.addCopySpec("/etc/xinetd.d") + self.addCopySpec("/etc/host*") + self.addCopySpec("/etc/resolv.conf") + # self.addCopySpec("/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") + ifconfigFile=self.collectExtOutput("/sbin/ifconfig -a") + self.collectExtOutput("/sbin/route -n") + self.collectExtOutput("/sbin/ipchains -nvL") + self.collectExtOutput("/sbin/iptables -t filter -nvL") + self.collectExtOutput("/sbin/iptables -t nat -nvL") + self.collectExtOutput("/sbin/iptables -t mangle -nvL") if ifconfigFile: for eth in self.get_interface_name(ifconfigFile): - self.runExe("/sbin/ethtool "+eth) + self.collectExtOutput("/sbin/ethtool "+eth) return diff --git a/src/lib/sos/plugins/pam.py b/src/lib/sos/plugins/pam.py index adce0046..364e81af 100644 --- a/src/lib/sos/plugins/pam.py +++ b/src/lib/sos/plugins/pam.py @@ -17,7 +17,7 @@ import sos.plugintools class pam(sos.plugintools.PluginBase): """This plugin gathers PAM related information """ - def collect(self): - self.copyFileOrDir("/etc/pam.d") + def setup(self): + self.addCopySpec("/etc/pam.d") return diff --git a/src/lib/sos/plugins/process.py b/src/lib/sos/plugins/process.py index d360af10..2cd1205b 100644 --- a/src/lib/sos/plugins/process.py +++ b/src/lib/sos/plugins/process.py @@ -17,8 +17,8 @@ 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") + def setup(self): + self.collectExtOutput("/bin/ps auxww") + self.collectExtOutput("/usr/bin/pstree") return diff --git a/src/lib/sos/plugins/rhn.py b/src/lib/sos/plugins/rhn.py index 512e0d7d..04222e61 100644 --- a/src/lib/sos/plugins/rhn.py +++ b/src/lib/sos/plugins/rhn.py @@ -17,7 +17,7 @@ from sos.plugintools import PluginBase class rhn(PluginBase): """This plugin gathers RHN server related information """ - def collect(self): + def setup(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") @@ -31,56 +31,56 @@ class rhn(PluginBase): # # basic RHN logs and configs - self.copyFileGlob("/var/log/rhn*") - self.copyFileOrDir("/etc/rhn") - self.runExe("/usr/share/rhn/up2date_client/hardware.py") + self.addCopySpec("/var/log/rhn*") + self.addCopySpec("/etc/rhn") + self.collectExtOutput("/usr/share/rhn/up2date_client/hardware.py") # httpd - self.copyFileOrDir("/etc/httpd/conf") - self.copyFileOrDir("/var/log/httpd") + self.addCopySpec("/etc/httpd/conf") + self.addCopySpec("/var/log/httpd") # RPM manifests - self.runExe("/bin/rpm -qa --last | sort") + self.collectExtOutput("/bin/rpm -qa --last | sort") # monitoring scout logs - self.copyFileGlob("/home/nocpulse/var/*.log*") - self.copyFileGlob("/home/nocpulse/var/commands/*.log*") + self.addCopySpec("/home/nocpulse/var/*.log*") + self.addCopySpec("/home/nocpulse/var/commands/*.log*") # # Now, go for product-specific data # if satellite: - self.collectSatellite(satellite) + self.setupSatellite(satellite) if proxy: - self.collectProxy(proxy) + self.setupProxy(proxy) - def collectSatellite(self, satellite): - self.runExe("/usr/bin/rhn-schema-version") - self.runExe("/usr/bin/rhn-charsets") + def setupSatellite(self, satellite): + self.collectExtOutput("/usr/bin/rhn-schema-version") + self.collectExtOutput("/usr/bin/rhn-charsets") # oracle - self.copyFileOrDir("/etc/tnsnames.ora") + self.addCopySpec("/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") + self.addCopySpec("/etc/tomcat5") + self.addCopySpec("/var/log/tomcat5") # jabberd # - logs to /var/log/messages - self.copyFileOrDir("/etc/jabberd") + self.addCopySpec("/etc/jabberd") # SSL build - self.copyFileOrDir("/root/ssl-build") + self.addCopySpec("/root/ssl-build") # monitoring logs - self.copyFileGlob("/opt/notification/var/*.log*") - self.copyFileGlob("/var/tmp/ack_handler.log*") - self.copyFileGlob("/var/tmp/enqueue.log*") + self.addCopySpec("/opt/notification/var/*.log*") + self.addCopySpec("/var/tmp/ack_handler.log*") + self.addCopySpec("/var/tmp/enqueue.log*") - def collectProxy(self, proxy): + def setupProxy(self, proxy): # squid - self.copyFileOrDir("/etc/squid") - self.copyFileOrDir("/var/log/squid") + self.addCopySpec("/etc/squid") + self.addCopySpec("/var/log/squid") diff --git a/src/lib/sos/plugins/rpm.py b/src/lib/sos/plugins/rpm.py index 44b9d5c8..f754a311 100644 --- a/src/lib/sos/plugins/rpm.py +++ b/src/lib/sos/plugins/rpm.py @@ -20,13 +20,13 @@ class rpm(sos.plugintools.PluginBase): 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") + def setup(self): + self.addCopySpec("/var/log/rpmpkgs") if self.isOptionEnabled("rpmq"): - self.runExe("/bin/rpm -qa --qf \"%{NAME}-%{VERSION}-%{RELEASE}-%{ARCH}\n\"") + self.collectExtOutput("/bin/rpm -qa --qf \"%{NAME}-%{VERSION}-%{RELEASE}-%{ARCH}\n\"") if self.isOptionEnabled("rpmva"): - self.runExe("/bin/rpm -Va") + self.collectExtOutput("/bin/rpm -Va") return diff --git a/src/lib/sos/plugins/samba.py b/src/lib/sos/plugins/samba.py index 848da265..17c0937f 100644 --- a/src/lib/sos/plugins/samba.py +++ b/src/lib/sos/plugins/samba.py @@ -17,9 +17,9 @@ 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") + def setup(self): + self.addCopySpec("/etc/samba") + self.collectExtOutput("/usr/bin/wbinfo -g") + self.collectExtOutput("/usr/bin/wbinfo -u") return diff --git a/src/lib/sos/plugins/selinux.py b/src/lib/sos/plugins/selinux.py index 51fe90d9..7ba1781b 100644 --- a/src/lib/sos/plugins/selinux.py +++ b/src/lib/sos/plugins/selinux.py @@ -17,10 +17,10 @@ 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") + def setup(self): + self.collectExtOutput("/usr/bin/selinuxconfig") + self.collectExtOutput("/usr/sbin/sestatus") + self.collectExtOutput("/bin/rpm -q -V selinux-policy-targeted") + self.collectExtOutput("/bin/rpm -q -V selinux-policy-strict") return diff --git a/src/lib/sos/plugins/squid.py b/src/lib/sos/plugins/squid.py index e552a99e..4522cb3b 100644 --- a/src/lib/sos/plugins/squid.py +++ b/src/lib/sos/plugins/squid.py @@ -17,7 +17,7 @@ import sos.plugintools class squid(sos.plugintools.PluginBase): """This plugin gathers Squid related information """ - def collect(self): - self.copyFileOrDir("/etc/squid/squid.conf") + def setup(self): + self.addCopySpec("/etc/squid/squid.conf") return diff --git a/src/lib/sos/plugins/startup.py b/src/lib/sos/plugins/startup.py index 820ee0e7..83ee5ba4 100644 --- a/src/lib/sos/plugins/startup.py +++ b/src/lib/sos/plugins/startup.py @@ -17,10 +17,10 @@ import sos.plugintools class startup(sos.plugintools.PluginBase): """This plugin gathers startup information """ - def collect(self): - self.copyFileOrDir("/etc/rc.d") + def setup(self): + self.addCopySpec("/etc/rc.d") - self.runExe("/sbin/chkconfig --list") - # self.runExe("/bin/ls /etc/rc.d/rc*.d/") # This is redundant. + self.collectExtOutput("/sbin/chkconfig --list") + # self.collectExtOutput("/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 index b98b40df..06bf65d1 100644 --- a/src/lib/sos/plugins/system.py +++ b/src/lib/sos/plugins/system.py @@ -17,15 +17,15 @@ 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.*") + def setup(self): + self.addCopySpec("/proc/sys") + self.addCopySpec("/etc/sysctl.conf") + self.addCopySpec("/etc/cron*") + self.addCopySpec("/etc/syslog.conf") + self.addCopySpec("/etc/ntp.conf") + self.addCopySpec("/etc/ntp/step-tickers") + self.addCopySpec("/etc/ntp/ntpservers") + self.addCopySpec("/etc/auto.*") return diff --git a/src/lib/sos/plugins/tarball.py b/src/lib/sos/plugins/tarball.py index 787ffed2..4162951a 100644 --- a/src/lib/sos/plugins/tarball.py +++ b/src/lib/sos/plugins/tarball.py @@ -28,14 +28,14 @@ class tarball(sos.plugintools.PluginBase): ticketNumber = sys.stdin.readline()[:-1] dirName = name + "." + ticketNumber - self.runExeInd("/bin/mkdir /tmp/%s" % dirName) - self.runExeInd("/bin/mv %s/* /tmp/%s" + self.callExtProg("/bin/mkdir /tmp/%s" % dirName) + self.callExtProg("/bin/mv %s/* /tmp/%s" % (dstroot, dirName)) - self.runExeInd("/bin/rm -rf %s" % dstroot) - self.runExeInd("/bin/tar --directory /tmp -jcf " + self.callExtProg("/bin/rm -rf %s" % dstroot) + self.callExtProg("/bin/tar --directory /tmp -jcf " "/tmp/%s.tar.bz2 %s" % (dirName, dirName)) - self.runExeInd("/bin/rm -rf /tmp/%s" % dirName) + self.callExtProg("/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 index 9d9b27c9..f7963eca 100644 --- a/src/lib/sos/plugins/x11.py +++ b/src/lib/sos/plugins/x11.py @@ -17,10 +17,10 @@ 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.'") + 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.'") return diff --git a/src/lib/sos/plugintools.py b/src/lib/sos/plugintools.py index b4aa9cf3..d67f17a4 100644 --- a/src/lib/sos/plugintools.py +++ b/src/lib/sos/plugintools.py @@ -18,23 +18,13 @@ ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. from sos.helpers import * +from threading import Thread 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) @@ -49,6 +39,9 @@ class PluginBase: self.optParms = [] self.piName = pluginname self.cInfo = commons + self.forbiddenPaths = [] + self.copyPaths = [] + self.collectProgs = [] # get the option list into a dictionary for opt in self.optionList: @@ -56,72 +49,20 @@ class PluginBase: 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): + def doCopyFileOrDir(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 ''' + copyProhibited = 0 + for path in self.forbiddenPaths: + if ( srcpath.count(path) > 0 ): + copyProhibited = 1 + + if copyProhibited: + return + 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 @@ -137,60 +78,154 @@ class PluginBase: 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}) + for file in os.listdir(srcpath): + if file == '.' or file == '..': + pass + else: + try: + self.doCopyFileOrDir(srcpath+'/'+file) + except: + sys.stderr.write("Problem at path %s\n" % srcpath+'/'+file,) + sys.stderr.flush() else: - dstslname, abspath = self.__copyFile(srcpath) + try: + dstslname, abspath = self.__copyFile(srcpath) + except: + sys.stderr.write("Problem at path %s\n" % srcpath) + sys.stderr.flush() 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) + try: + self.doCopyFileOrDir(newpath) + except: + sys.stderr.write("Problem at path %s" % newpath,) + sys.stderr.flush 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 + for file in os.listdir(srcpath): + if file == '.' or file == '..': + pass + else: + self.doCopyFileOrDir(srcpath+'/'+file) 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 + 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. + """ + try: + 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 + except Exception,e: + sys.stderr.write("Problem copying file %s\n" % src,) + print 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. + """ + self.forbiddenPaths.append(forbiddenPath) + + 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 addCopySpec(self, copyspec): + """ Add a file specification (can be file, dir,or shell glob) to be + copied into the sosreport by this module + """ + # 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 - """ - + """ # First check to make sure the binary exists and is runnable. - if not os.access(exe.split()[0], os.X_OK): + if not os.access(prog.split()[0], os.X_OK): return - - status, shout, sherr = sosGetCommandOutput(exe) + + status, shout, sherr = 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 - return status + def collectExtOutput(self, exe): + self.collectProgs.append(exe) - def runExe(self, exe): + def collectOutputNow(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) @@ -211,11 +246,11 @@ class PluginBase: outfd.write(shout) outfd.close() self.cInfo['logfd'].write(sherr) - sosStatus(status) + # 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 @@ -232,13 +267,40 @@ class PluginBase: self.customText = self.customText + text return - - # What follows are the methods which may be overridden by the plugin - - + def doCollect(self): + self.thread = Thread(target=self.copyStuff,name=self.piName+'-thread') + self.thread.start() + + def wait(self): + self.thread.join() + + def copyStuff(self): + for path in self.copyPaths: + try: + self.doCopyFileOrDir(path) + except Exception, e: + sys.stderr.write("Error copying from pathspec %s\n" % path,) + print e + sys.stderr.flush() + for prog in self.collectProgs: + try: + self.collectOutputNow(prog) + except: + sys.stderr.write("Error collecting output of '%s'\n" % prog,) + sys.stderr.flush() + def collect(self): + """ This function has been replaced with setup(). Please change your + module calls. Calling setup() now. + """ + self.setup() + + def setup(self): + """This class must be overridden to add the copyPaths, forbiddenPaths, + and external programs to be collected at a minimum. + """ pass - + def analyze(self): pass diff --git a/src/sosreport b/src/sosreport index 5ebea18f..5aa7063f 100755 --- a/src/sosreport +++ b/src/sosreport @@ -26,6 +26,7 @@ from optparse import OptionParser import sos.policyredhat from sos.helpers import * from snack import * +from threading import Thread if os.getuid() != 0: print 'You must run sosreport as root!' @@ -109,6 +110,7 @@ def sosreport(): "This is the top-level function that gathers and processes all sosreport information" loadedplugins = [] alloptions = [] + threads = [] # TODO automatically locate the policy module?? policy = sos.policyredhat.SosPolicy() @@ -206,9 +208,17 @@ def sosreport(): for plug, plugname, optname, optparm in alloptions: plug.setOption(optname,1) + # Call the setup method for each plugin + for plugname, plug in loadedplugins: + plug.setup() + # Call the collect method for each plugin for plugname, plug in loadedplugins: - plug.collect() + plug.doCollect() + + # Wait for all the collcetion threads to exit + for plugname, plug in loadedplugins: + plug.wait() # Call the analyze method for each plugin for plugname, plug in loadedplugins: |