aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorshnavid <shnavid@ef72aa8b-4018-0410-8976-d6e080ef94d8>2007-06-15 11:59:03 +0000
committershnavid <shnavid@ef72aa8b-4018-0410-8976-d6e080ef94d8>2007-06-15 11:59:03 +0000
commit8a72411156d4fe6cdca99317c2f6b87a46100286 (patch)
tree841cde5d71ff1f7d8dc36477e1b843e2229fbd83
parentfdaedd36fca0e15829d1dca06ee7a0c95541c59f (diff)
downloadsos-8a72411156d4fe6cdca99317c2f6b87a46100286.tar.gz
* Initial commit of XML reporting to gather details about commands executed and files gathered.
git-svn-id: svn+ssh://svn.fedorahosted.org/svn/sos/trunk@144 ef72aa8b-4018-0410-8976-d6e080ef94d8
-rwxr-xr-xsrc/lib/sos/helpers.py4
-rw-r--r--src/lib/sos/plugintools.py20
-rwxr-xr-xsrc/lib/sos/policyredhat.py2
-rwxr-xr-xsrc/sosreport80
4 files changed, 98 insertions, 8 deletions
diff --git a/src/lib/sos/helpers.py b/src/lib/sos/helpers.py
index 5524c0e4..8ba503c1 100755
--- a/src/lib/sos/helpers.py
+++ b/src/lib/sos/helpers.py
@@ -26,6 +26,7 @@
helper functions used by sosreport and plugins
"""
import os, popen2, fcntl, select, itertools, sys
+from time import time
from tempfile import mkdtemp
def importPlugin(pluginname, name):
@@ -60,6 +61,7 @@ def sosGetCommandOutput(command):
""" Execute a command and gather stdin, stdout, and return status.
Adapted from Python Cookbook - O'Reilly
"""
+ stime = time()
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
@@ -89,7 +91,7 @@ def sosGetCommandOutput(command):
break
select.select([], [], [], .1) # Allow a little time for buffers to fill
err = child.wait()
- return (err, ''.join(outdata), ''.join(errdata))
+ return (err, ''.join(outdata), ''.join(errdata), time()-stime)
# this needs to be made clean and moved to the plugin tools, so
diff --git a/src/lib/sos/plugintools.py b/src/lib/sos/plugintools.py
index 5c301ed6..27203765 100644
--- a/src/lib/sos/plugintools.py
+++ b/src/lib/sos/plugintools.py
@@ -150,6 +150,7 @@ class PluginBase:
try:
dstslname, abspath = self.__copyFile(srcpath)
self.copiedFiles.append({'srcpath':srcpath, 'dstpath':dstslname, 'symlink':"yes", 'pointsto':link})
+ self.cInfo['xmlreport'].add_file(srcpath,os.stat(srcpath))
except SystemExit:
raise SystemExit
except KeyboardInterrupt:
@@ -194,7 +195,7 @@ class PluginBase:
"""
try:
# pylint: disable-msg = W0612
- status, shout, sherr = sosGetCommandOutput("/bin/cp --parents -p " + src +" " + self.cInfo['dstroot'])
+ status, shout, sherr, runtime = sosGetCommandOutput("/bin/cp --parents -p " + src +" " + self.cInfo['dstroot'])
if status:
self.cInfo['soslog'].debug(shout)
self.cInfo['soslog'].debug(sherr)
@@ -277,7 +278,7 @@ class PluginBase:
return
# pylint: disable-msg = W0612
- status, shout, sherr = sosGetCommandOutput(prog)
+ status, shout, sherr, runtime = sosGetCommandOutput(prog)
return status
def runExe(self, exe):
@@ -320,17 +321,28 @@ class PluginBase:
return
# pylint: disable-msg = W0612
- status, shout, sherr = sosGetCommandOutput(exe)
+ status, shout, sherr, runtime = sosGetCommandOutput(exe)
outfn = self.makeCommandFilename(exe)
outfd = open(outfn, "w")
outfd.write(shout)
outfd.close()
- self.cInfo['soslog'].debug(sherr)
+ outfn = outfn[len(self.cInfo['cmddir'])+1:]
+ if len(sherr) > 0:
+ errfn = outfn + ".err"
+ outfd = open(errfn, "w")
+ outfd.write(sherr)
+ outfd.close()
+ errfn = errfn[len(self.cInfo['cmddir'] + "/" )+1:]
+ self.cInfo['soslog'].debug(sherr)
+ else:
+ errfn = None
+
# sosStatus(status)
# save info for later
self.executedCommands.append({'exe': exe, 'file':outfn}) # save in our list
+ self.cInfo['xmlreport'].add_command(cmdline=exe,exitcode=status,f_stdout=outfn,f_stderr=errfn,runtime=runtime)
return outfn
def writeTextToCommand(self, exe, text):
diff --git a/src/lib/sos/policyredhat.py b/src/lib/sos/policyredhat.py
index 08e0f9b3..80643576 100755
--- a/src/lib/sos/policyredhat.py
+++ b/src/lib/sos/policyredhat.py
@@ -111,7 +111,7 @@ class SosPolicy:
os.chdir(ourtempdir)
oldmask = os.umask(077)
# pylint: disable-msg = W0612
- status, shout, sherr = sosGetCommandOutput(tarcmd)
+ status, shout, sherr, runtime = sosGetCommandOutput(tarcmd)
os.umask(oldmask)
os.chdir(curwd)
os.system("/bin/mv %s %s" % (aliasdir, self.cInfo['dstroot']))
diff --git a/src/sosreport b/src/sosreport
index 119f319e..1bf8b981 100755
--- a/src/sosreport
+++ b/src/sosreport
@@ -35,6 +35,9 @@ from snack import *
from threading import Thread, activeCount, enumerate
import signal
import logging
+from stat import *
+from time import strftime, localtime
+from pwd import getpwuid
__breakHits__ = 0 # Use this to track how many times we enter the exit routine
@@ -224,7 +227,74 @@ class progressBar:
def update(self):
sys.stdout.write(self.progBar + '\r')
sys.stdout.flush()
-
+
+class XmlReport:
+ def __init__(self):
+ try:
+ import libxml2
+ except:
+ self.enabled = False
+ return
+ else:
+ self.enabled = True
+ self.doc = libxml2.newDoc("1.0")
+ self.root = self.doc.newChild(None, "sos", None)
+ self.commands = self.root.newChild(None, "commands", None)
+ self.files = self.root.newChild(None, "files", None)
+
+ def add_command(self,cmdline,exitcode,stdout = None,stderr = None,f_stdout=None,f_stderr=None, runtime=None):
+ if not self.enabled: return
+
+ cmd = self.commands.newChild(None, "cmd", None)
+
+ cmd.setNsProp(None, "cmdline", cmdline)
+
+ cmdchild = cmd.newChild(None, "exitcode", str(exitcode))
+
+ if runtime:
+ cmd.newChild(None, "runtime", str(runtime))
+
+ if stdout or f_stdout:
+ cmdchild = cmd.newChild(None, "stdout", stdout)
+ if f_stdout:
+ cmdchild.setNsProp(None, "file", f_stdout)
+
+ if stderr or f_stderr:
+ cmdchild = cmd.newChild(None, "stderr", stderr)
+ if f_stderr:
+ cmdchild.setNsProp(None, "file", f_stderr)
+
+ def add_file(self,fname,stats):
+ if not self.enabled: return
+
+ cfile = self.files.newChild(None,"file",None)
+
+ cfile.setNsProp(None, "fname", fname)
+
+ cchild = cfile.newChild(None, "uid", str(stats[ST_UID]))
+ cchild.setNsProp(None,"name", getpwuid(stats[ST_UID])[0])
+ cchild = cfile.newChild(None, "gid", str(stats[ST_GID]))
+ cchild.setNsProp(None,"name", getpwuid(stats[ST_GID])[0])
+ cfile.newChild(None, "mode", str(oct(S_IMODE(stats[ST_MODE]))))
+ cchild = cfile.newChild(None, "ctime", strftime('%a %b %d %H:%M:%S %Y', localtime(stats[ST_CTIME])))
+ cchild.setNsProp(None,"tstamp", str(stats[ST_CTIME]))
+ cchild = cfile.newChild(None, "atime", strftime('%a %b %d %H:%M:%S %Y', localtime(stats[ST_ATIME])))
+ cchild.setNsProp(None,"tstamp", str(stats[ST_ATIME]))
+ cchild = cfile.newChild(None, "mtime", strftime('%a %b %d %H:%M:%S %Y', localtime(stats[ST_MTIME])))
+ cchild.setNsProp(None,"tstamp", str(stats[ST_MTIME]))
+
+ def serialize(self):
+ if not self.enabled: return
+
+ print self.doc.serialize(None, 1)
+
+ def serialize_to_file(self,fname):
+ if not self.enabled: return
+
+ outfn = open(fname,"w")
+ outfn.write(self.doc.serialize(None,1))
+ outfn.close()
+
def sosreport():
# pylint: disable-msg = R0912
# pylint: disable-msg = R0914
@@ -277,9 +347,12 @@ def sosreport():
logging.addLevelName(logging.VERBOSE3,"verbose3")
soslog = logging.getLogger('')
+ xmlrep = XmlReport()
+
# set up dict so everyone can share the following
commons = {'dstroot': dstroot, 'cmddir': cmddir, 'logdir': logdir, 'rptdir': rptdir,
- 'soslog': soslog, 'policy': policy, 'verbosity' : __cmdLineOpts__.verbosity}
+ 'soslog': soslog, 'policy': policy, 'verbosity' : __cmdLineOpts__.verbosity,
+ 'xmlreport' : xmlrep }
# Make policy aware of the commons
@@ -392,6 +465,9 @@ def sosreport():
pbar.incAmount(30)
pbar.update()
+ xmlrep.serialize()
+ xmlrep.serialize_to_file(rptdir + "/" + "sosreport.xml")
+
# Wait for all the collection threads to exit
if __cmdLineOpts__.multithread:
for plugname, plug in loadedplugins: