aboutsummaryrefslogblamecommitdiffstats
path: root/src/sosreport
blob: a842f3eefab44d19db37aca25ac06927b91ebbb5 (plain) (tree)
1
2
3
4
5
6
7
                     



                                                             
               
                                                  
















                                                                        


                             

          
              



                                 
                            





                                           






















                                                                                                                   

                                  


                                                        
                                                                                    

                 

                                           


                                   

                   
                                               
 
                 
 

                     


                                           

                                                             




                                     



                                                                                                                      






                                                                
               


                   


                                                                   




                





                                                                                       


                      
                                                                







                                                                    



















                                                                                                                          
                                   

















                                                                      
                                                                   


                                                                            
                                                                                    


                                                                       
                   
                                    






                                                        
                                         
                                                                 
            

                                                         


                                                                         




                                                                     


                                                                          

                                                               


                                              

                                                               
                                          
 

                                           
                                         
                                                           

                    

                                             



                                                     
             
                                                         

                                                 




                                                                   


                                             
                                         
                                                              
                                               



























                                                                                                                 







                                                                                      


                                                                                   
                            




































                                                                   
#!/usr/bin/env python
"""
Gather information about a system and report it using plugins
supplied for application-specific information
"""
## sosreport.py
## gather information about a system and report it

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

# pylint: disable-msg = W0611
# pylint: disable-msg = W0702

import sys
import os
#import curses
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!'
    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")
__cmdParser__.add_option("-v", "--verbose", action="count", \
                     dest="verbosity", \
                     help="How obnoxious we're being about telling the user what we're doing.")
__cmdParser__.add_option("-m", "--multithreaded", action="store_true", \
                     dest="multithread", \
                     help="Use the multithreaded information gathering mode to speed up the report (experimental)")
(__cmdLineOpts__, __cmdLineArgs__)=__cmdParser__.parse_args()

def get_curse_options(alloptions):
    """
    use curses to enable the user to select some options
    """
    # allooptions is an array of (plug, plugname, optname, parms(dictionary)) tuples
    plugName = []
    out = []
    
    # get a sorted list of all plugin names
    for rrr in alloptions:
        if rrr[1] not in plugName:
            plugName.append(rrr[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

            snt = opt[2] + " ("+opt[3]['desc']+") is " + opt[3]['speed']
            plugCbox.addItem(snt, (countOpt, snackArgs['append']), item = optDicCounter, selected = opt[3]['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)
    g.runOnce()

    screen.finish()

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

    return out

    
def sosreport():
    # pylint: disable-msg = R0912
    # pylint: disable-msg = R0914
    # pylint: disable-msg = R0915
    """
    This is the top-level function that gathers and processes all sosreport information
    """
    loadedplugins = []
    alloptions = []

    # perhaps we should 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"

    # 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
            except:
                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:
        if __cmdLineOpts__.verbosity > 3:
            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:
        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 setup method for each plugin
    for plugname, plug in loadedplugins:
        if __cmdLineOpts__.verbosity > 1:
            print "Setting up plugin module %s" % plugname,
        plug.setup()

    # Call the collect method for each plugin
    for plugname, plug in loadedplugins:
        if __cmdLineOpts__.verbosity > 0:
            print "Executing plugin %s" % plugname
        if __cmdLineOpts__.multithread:
            plug.doCollect(__cmdLineOpts__.verbosity)
        else:
            plug.copyStuff(__cmdLineOpts__.verbosity)    

    # Wait for all the collection threads to exit
    if __cmdLineOpts__.multithread:
        for plugname, plug in loadedplugins:
            if __cmdLineOpts__.verbosity > 1:
                print "Waiting for plugin %s to return" % plugname,
            plug.wait()

    # Call the analyze method for each plugin
    for plugname, plug in loadedplugins:
        if __cmdLineOpts__.verbosity > 1:
            print "Analyzing results of plugin %s" % plugname,
        plug.analyze(__cmdLineOpts__.verbosity)

    # 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:
            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")
    rr = 0
    for i in range(len(plugNames)):
        rfd.write('<td><a href="#%s">%s</a></td>\n' % (plugNames[i], plugNames[i]))
        rr = divmod(i, 4)[1]
        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()