aboutsummaryrefslogblamecommitdiffstats
path: root/src/sosreport
blob: 5ebea18fa934af39ced2ae82b5cb2f141743a327 (plain) (tree)





































































































































































































































































































                                                                                                                                               
#!/usr/bin/env python

## sosreport.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.

import sys
import os
import curses
from optparse import OptionParser
import sos.policyredhat
from sos.helpers import *
from snack import *

if os.getuid() != 0:
    print 'You must run sosreport as root!'
    sys.exit(1)

# for debugging
raiseplugins = 1


cmdParser=OptionParser()
cmdParser.add_option("-a","--alloptions",action="store_true",dest="alloptions",default=False,help="Use all options for loaded plugins")
cmdParser.add_option("-f","--fastoptions",action="store_true",dest="fastoptions",default=False,help="Use only fast options for loaded plugins")
cmdParser.add_option("-l","--list-plugins",action="store_true",dest="listPlugins",default=False,help="list existing plugins")
cmdParser.add_option("-n","--noplugin",action="append",dest="noplugins",help="list of plugin _not_ to load")

(cmdLineOpts,cmdLineArgs)=cmdParser.parse_args()
#print cmdLineOpts

def get_curse_options(alloptions):
    #http://www.amk.ca/python/howto/curses/
    #http://gnosis.cx/publish/programming/charming_python_6.html
    #http://www.wanware.com/tsgdocs/snack.html
    # /usr/share/doc/newt-devel-0.51.6/ 
    #

    # allooptions is an array of (plug, plugname, optname, parms(dictionary)) tuples
    plugName=[]
    out=[]
    
    # get a sorted list of all plugin names
    for p in alloptions:
        if p[1] not in plugName:
            plugName.append(p[1])

    plugName.sort()
    plugCbox=CheckboxTree(height=5,scroll=1)

    countOpt=-1

    optDic={}
    optDicCounter=0

    # iterate over all plugins with options
    for curPlugName in plugName:
        plugCbox.addItem(curPlugName,(snackArgs['append'],))
        countOpt=countOpt+1

        for opt in alloptions:
            if opt[1] != curPlugName:
                continue

            optName=opt[2]
            enabled=opt[3]['enabled']
            speed=opt[3]['speed']
            optDesc=opt[3]['desc']

            snt=optName+" ("+optDesc+") is "+speed
            plugCbox.addItem(snt,(countOpt,snackArgs['append']),item=optDicCounter,selected=enabled)
            optDic[optDicCounter]=opt
            optDicCounter+=1
            

    screen = SnackScreen()
    bb = ButtonBar(screen, (("Ok", "ok"), ("Cancel", "cancel")))
    g = GridForm(screen, "Select Sosreport Options", 1, 10)
    g.add(plugCbox, 0, 0)
    g.add(bb, 0, 1, growx = 1)
    result = g.runOnce()

    screen.finish()

    for i in range(0, optDicCounter):
        froo, wantit = plugCbox.getEntryValue(i)
        optDic[i][3]['enabled'] = wantit
        out.append((optDic[i]))

    return out

    
def sosreport():
    "This is the top-level function that gathers and processes all sosreport information"
    loadedplugins = []
    alloptions = []

    # TODO automatically locate the policy module??
    policy = sos.policyredhat.SosPolicy()

    # find the plugins path
    paths = sys.path
    for path in paths:
        if  path.strip()[-len("site-packages"):] == "site-packages":
            pluginpath = path + "/sos/plugins"

    # TODO process command line to:
    # load unsigned plugins
    # disable one or more plugins
    # set fast or slow collection without options menu presentation

    # Set up common info and create destinations
    
    dstroot = sosFindTmpDir()
    os.chmod(dstroot, 0755)
    cmddir = os.path.join(dstroot, "sos_commands")
    logdir = os.path.join(dstroot, "sos_logs")
    rptdir = os.path.join(dstroot, "sos_reports")
    os.mkdir(cmddir, 0755)
    os.mkdir(logdir, 0755)
    os.mkdir(rptdir, 0755)

    # open log file
    logfd = open(logdir + "/sos.log", "w")

    # set up dict so everyone can share the following
    commons = {'dstroot': dstroot, 'cmddir': cmddir, 'logdir': logdir, 'rptdir': rptdir, 'logfd': logfd, 'policy': policy}


    # validate and load plugins
    plugins = os.listdir(pluginpath)
    if cmdLineOpts.listPlugins:
        for plug in plugins:
            try:
                if ((plug[-3:] == '.py') and (plug != "__init__.py")):
                    plugbase =  plug[:-3]
                    pidot = "sos.plugins." + plugbase
                    print plugbase
            except:
                print "ouch"
        sys.exit()

    for plug in plugins:
        if ((plug[-3:] == '.py') and (plug != "__init__.py")):
            try:
                plugbase =  plug[:-3]
                pidot = "sos.plugins." + plugbase
                #print "importing plugin: %s" % plugbase
                try:
                    if policy.validatePlugin(pluginpath + plug):
                        PluginClass = importPlugin(pidot, plugbase)
                    else:
                        print "Plugin %s does not validate, skipping" % plug
                        continue
                    loadedplugins.append((plugbase, PluginClass(plugbase, commons)))
                except:
                    print "Plugin %s does not install, skipping" % plug
                    raise
                    continue    
            except:
                # TODO do better
                if raiseplugins:
                    raise
                print "plugin load failed for %s" % plug

    # Iterate over plugins for each stage

    # First, gather and process options
    for plugname, plug in loadedplugins:
        #print "processing options from plugin: %s" % plugname
        try:
            len(cmdLineOpts.noplugins)
            if plugname not in cmdLineOpts.noplugins:
                        names, parms = plug.getAllOptions()
                        for optname, optparm  in zip(names, parms):
                            alloptions.append((plug, plugname, optname, optparm))
        except:
            names, parms = plug.getAllOptions()
            for optname, optparm  in zip(names, parms):
                alloptions.append((plug, plugname, optname, optparm))

    if not cmdLineOpts.fastoptions and not cmdLineOpts.alloptions:
        cursedOptions=get_curse_options(alloptions)
    elif cmdLineOpts.fastoptions:
        for i in range(len(alloptions)):
            for plug, plugname, optname, optparm in alloptions:
                if optparm['speed']=='fast':
                    plug.setOption(optname,1)
    elif cmdLineOpts.alloptions:
        for i in range(len(alloptions)):
            for plug, plugname, optname, optparm in alloptions:
                plug.setOption(optname,1)

    # Call the collect method for each plugin
    for plugname, plug in loadedplugins:
        plug.collect()

    # Call the analyze method for each plugin
    for plugname, plug in loadedplugins:
        plug.analyze()

    # Sort the module names to do the report in alphabetical order
    loadedplugins.sort()

    # Generate the header for the html output file
    rfd = open(rptdir + "/" + "sosreport.html", "w")
    rfd.write("""
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
        <head>
    <link rel="stylesheet" type="text/css" media="screen" href="donot.css" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Sos System Report</title>
        </head>

        <body>
    """)

    rfd.write("Sosreport version blah blah<br />")

    


    # Make a pass to gather Alerts and a list of module names
    allAlerts = []
    plugNames = []
    for plugname, plug in loadedplugins:
        for alert in plug.alerts:
            # TODO include the plugin as a target of a link here
            allAlerts.append('<a href="#%s">%s</a>: %s' % (plugname, plugname, alert))
        plugNames.append(plugname)



    # Create a table of links to the module info
    rfd.write("<hr/><h3>Loaded Plugins:</h3>")
    rfd.write("<table><tr>\n")
    qq = 0
    rr = 0
    for i in range(len(plugNames)):
        rfd.write('<td><a href="#%s">%s</a></td>\n' % (plugNames[i], plugNames[i]))
        qq, rr = divmod(i,4)
        if (rr == 3):
            rfd.write('</tr>')
    if not (rr == 3):
        rfd.write('</tr>')
    rfd.write('</table>\n')

    rfd.write('<hr/><h3>Alerts:</h3>')
    rfd.write('<ul>')
    for alert in allAlerts:
        rfd.write('<li>%s</li>' % alert)
    rfd.write('</ul>')


    # Call the report method for each plugin
    for plugname, plug in loadedplugins:
        html = plug.report()
        rfd.write(html)

    rfd.write("</body></html>")

    rfd.close()

    # Collect any needed user information (name, etc)

    # Clean up left over files, make tarball, whatever.
    # Close all log files and perform any cleanup
    logfd.close()

    # Call the postproc method for each plugin
    for plugname, plug in loadedplugins:
        root = plug.postproc(dstroot)

    if root == dstroot:
        print "The report is in " + rptdir + "/" + "sosreport.html"
    
if __name__ == '__main__':
    sosreport()