Blame gfs2/scripts/gfs2_trace

Packit Service 360c39
#!/usr/bin/env python
Packit Service 360c39
"""
Packit Service 360c39
This script will enable or disable trace events for GFS2. The script can capture
Packit Service 360c39
trace events and write the trace events captured to a file.
Packit Service 360c39
Packit Service 360c39
When capturing events, hit "control-c" to exit and then the capture events will be
Packit Service 360c39
written to a file. A file will be created by reading this pipe:
Packit Service 360c39
/sys/kernel/debug/tracing/trace_pipe
Packit Service 360c39
Packit Service 360c39
The debug directory is required to be mounted which will be mounted if not
Packit Service 360c39
mounted. The trace events are located in this directory
Packit Service 360c39
/sys/kernel/debug/tracing/events/gfs2.
Packit Service 360c39
Packit Service 360c39
The file that can be used to validate what fields are valid for "filters" is
Packit Service 360c39
described in the format file. For example:
Packit Service 360c39
/sys/kernel/debug/tracing/events/gfs2/*/format
Packit Service 360c39
Packit Service 360c39
@author    :  Shane Bradley
Packit Service 360c39
@contact   :  sbradley@redhat.com
Packit Service 360c39
@version   :  0.9
Packit Service 360c39
@copyright :  GPLv2
Packit Service 360c39
"""
Packit Service 360c39
import sys
Packit Service 360c39
import os
Packit Service 360c39
import os.path
Packit Service 360c39
import logging
Packit Service 360c39
import platform
Packit Service 360c39
import fileinput
Packit Service 360c39
import tarfile
Packit Service 360c39
import subprocess
Packit Service 360c39
from optparse import OptionParser, Option
Packit Service 360c39
Packit Service 360c39
# #####################################################################
Packit Service 360c39
# Global Vars:
Packit Service 360c39
# #####################################################################
Packit Service 360c39
"""
Packit Service 360c39
@cvar VERSION_NUMBER: The version number of this script.
Packit Service 360c39
@type VERSION_NUMBER: String
Packit Service 360c39
@cvar MAIN_LOGGER_NAME: The name of the logger.
Packit Service 360c39
@type MAIN_LOGGER_NAME: String
Packit Service 360c39
@cvar PATH_TO_DEBUG_DIR: The path to the debug directory for the linux kernel.
Packit Service 360c39
@type PATH_TO_DEBUG_DIR: String
Packit Service 360c39
@cvar PATH_TO_PID_FILENAME: The path to the pid file that will be used to make
Packit Service 360c39
sure only 1 instance of this script is running at any time.
Packit Service 360c39
@type PATH_TO_PID_FILENAME: String
Packit Service 360c39
@cvar PATH_TO_GFS2_TRACE_EVENTS_DIR: The path to the directory that contains
Packit Service 360c39
all the GFS2 trace events.
Packit Service 360c39
@type PATH_TO_GFS2_TRACE_EVENTS_DIR: String
Packit Service 360c39
@cvar PATH_TO_TRACE_PIPE: The path to the tracing pipe.
Packit Service 360c39
@type PATH_TO_TRACE_PIPE: String
Packit Service 360c39
"""
Packit Service 360c39
VERSION_NUMBER = "0.9-1"
Packit Service 360c39
MAIN_LOGGER_NAME = "gfs2trace"
Packit Service 360c39
PATH_TO_DEBUG_DIR="/sys/kernel/debug"
Packit Service 360c39
PATH_TO_PID_FILENAME = "/var/run/%s.pid" %(os.path.basename(sys.argv[0]))
Packit Service 360c39
PATH_TO_GFS2_TRACE_EVENTS_DIR="%s/tracing/events/gfs2" %(PATH_TO_DEBUG_DIR)
Packit Service 360c39
PATH_TO_TRACE_PIPE="%s/tracing/trace_pipe" %(PATH_TO_DEBUG_DIR)
Packit Service 360c39
Packit Service 360c39
class FileUtils:
Packit Service 360c39
    """
Packit Service 360c39
    A class that provides static functions for files such as reading and
Packit Service 360c39
    writing.
Packit Service 360c39
    """
Packit Service 360c39
    def getDataFromFile(pathToSrcFile) :
Packit Service 360c39
        """
Packit Service 360c39
        This function will return the data in an array. Where each newline in file
Packit Service 360c39
        is a seperate item in the array. This should really just be used on
Packit Service 360c39
        relatively small files.
Packit Service 360c39
Packit Service 360c39
        None is returned if no file is found.
Packit Service 360c39
Packit Service 360c39
        @return: Returns an array of Strings, where each newline in file is an item
Packit Service 360c39
        in the array.
Packit Service 360c39
        @rtype: Array
Packit Service 360c39
Packit Service 360c39
        @param pathToSrcFile: The path to the file which will be read.
Packit Service 360c39
        @type pathToSrcFile: String
Packit Service 360c39
        """
Packit Service 360c39
        if (len(pathToSrcFile) > 0) :
Packit Service 360c39
            try:
Packit Service 360c39
                fin = open(pathToSrcFile, "r")
Packit Service 360c39
                data = fin.readlines()
Packit Service 360c39
                fin.close()
Packit Service 360c39
                return data
Packit Service 360c39
            except (IOError, os.error):
Packit Service 360c39
                message = "An error occured reading the file: %s." %(pathToSrcFile)
Packit Service 360c39
                logging.getLogger(MAIN_LOGGER_NAME).error(message)
Packit Service 360c39
        return None
Packit Service 360c39
    getDataFromFile = staticmethod(getDataFromFile)
Packit Service 360c39
Packit Service 360c39
    def writeToFile(pathToFilename, data, appendToFile=True, createFile=False):
Packit Service 360c39
        """
Packit Service 360c39
        This function will write a string to a file.
Packit Service 360c39
Packit Service 360c39
        @return: Returns True if the string was successfully written to the file,
Packit Service 360c39
        otherwise False is returned.
Packit Service 360c39
        @rtype: Boolean
Packit Service 360c39
Packit Service 360c39
        @param pathToFilename: The path to the file that will have a string written
Packit Service 360c39
        to it.
Packit Service 360c39
        @type pathToFilename: String
Packit Service 360c39
        @param data: The string that will be written to the file.
Packit Service 360c39
        @type data: String
Packit Service 360c39
        @param appendToFile: If True then the data will be appened to the file, if
Packit Service 360c39
        False then the data will overwrite the contents of the file.
Packit Service 360c39
        @type appendToFile: Boolean
Packit Service 360c39
        @param createFile: If True then the file will be created if it does not
Packit Service 360c39
        exists, if False then file will not be created if it does not exist
Packit Service 360c39
        resulting in no data being written to the file.
Packit Service 360c39
        @type createFile: Boolean
Packit Service 360c39
        """
Packit Service 360c39
        [parentDir, filename] = os.path.split(pathToFilename)
Packit Service 360c39
        if (os.path.isfile(pathToFilename) or (os.path.isdir(parentDir) and createFile)):
Packit Service 360c39
            try:
Packit Service 360c39
                filemode = "w"
Packit Service 360c39
                if (appendToFile):
Packit Service 360c39
                    filemode = "a"
Packit Service 360c39
                fout = open(pathToFilename, filemode)
Packit Service 360c39
                fout.write(data + "\n")
Packit Service 360c39
                fout.close()
Packit Service 360c39
                return True
Packit Service 360c39
            except UnicodeEncodeError as e:
Packit Service 360c39
                message = "There was a unicode encode error writing to the file: %s." %(pathToFilename)
Packit Service 360c39
                logging.getLogger(MAIN_LOGGER_NAME).error(message)
Packit Service 360c39
                return False
Packit Service 360c39
            except IOError:
Packit Service 360c39
                message = "There was an error writing to the file: %s." %(pathToFilename)
Packit Service 360c39
                logging.getLogger(MAIN_LOGGER_NAME).error(message)
Packit Service 360c39
                return False
Packit Service 360c39
        return False
Packit Service 360c39
    writeToFile = staticmethod(writeToFile)
Packit Service 360c39
Packit Service 360c39
class TraceEvent:
Packit Service 360c39
    """
Packit Service 360c39
    A class that reprensents a trace event.
Packit Service 360c39
    """
Packit Service 360c39
    def __init__(self, pathToTraceEvent):
Packit Service 360c39
        """
Packit Service 360c39
        @param pathToTraceEvent: The path to the trace event directory.
Packit Service 360c39
        @type pathToTraceEvent: String
Packit Service 360c39
        """
Packit Service 360c39
        self.__pathToTraceEvent = pathToTraceEvent
Packit Service 360c39
Packit Service 360c39
    def __str__(self):
Packit Service 360c39
        """
Packit Service 360c39
        Returns a string representation of a TraceEvent.
Packit Service 360c39
Packit Service 360c39
        @return: Returns a string representation of a TraceEvent.
Packit Service 360c39
        @rtype: String
Packit Service 360c39
        """
Packit Service 360c39
        return "%s: %s" %(self.getName(), self.getEnable())
Packit Service 360c39
Packit Service 360c39
    def __getEventPathItem(self, pathToFilename):
Packit Service 360c39
        """
Packit Service 360c39
        Returns the data contain in the file. If file does not exist then empty
Packit Service 360c39
        array is returned.
Packit Service 360c39
Packit Service 360c39
        @return: Returns the data contained in the file. If file does not exist
Packit Service 360c39
        then empty array is returned.
Packit Service 360c39
        @rtype: Array
Packit Service 360c39
Packit Service 360c39
        @param pathToFilename: The path to the filename of the file in the trace
Packit Service 360c39
        event's directory.
Packit Service 360c39
        @type pathToFilename: String
Packit Service 360c39
        """
Packit Service 360c39
        output = FileUtils.getDataFromFile(pathToFilename)
Packit Service 360c39
        if (output == None):
Packit Service 360c39
            return []
Packit Service 360c39
        return output
Packit Service 360c39
Packit Service 360c39
    def __setEventPathItem(self, pathToFilename, contentsOfEventItem, appendToFile=True):
Packit Service 360c39
        """
Packit Service 360c39
        This function will write data to a file in the trace event's directory.
Packit Service 360c39
Packit Service 360c39
        @return: Returns True is data was successfully written.
Packit Service 360c39
        @rtype: Boolean
Packit Service 360c39
        """
Packit Service 360c39
        return FileUtils.writeToFile(pathToFilename, contentsOfEventItem, appendToFile)
Packit Service 360c39
Packit Service 360c39
    def getPathToTraceEvent(self):
Packit Service 360c39
        """
Packit Service 360c39
        Returns the path to the trace event directory.
Packit Service 360c39
Packit Service 360c39
        @return: Returns the path to the trace event directory.
Packit Service 360c39
        @rtype: String
Packit Service 360c39
        """
Packit Service 360c39
        return self.__pathToTraceEvent
Packit Service 360c39
Packit Service 360c39
    def getName(self):
Packit Service 360c39
        """
Packit Service 360c39
        Returns the shortname of the trace event.
Packit Service 360c39
Packit Service 360c39
        @return: Returns the shortname of the trace event.
Packit Service 360c39
        @rtype: String
Packit Service 360c39
        """
Packit Service 360c39
        return os.path.basename(self.getPathToTraceEvent())
Packit Service 360c39
Packit Service 360c39
    def getEnable(self):
Packit Service 360c39
        """
Packit Service 360c39
        Returns the contents of the file "enable" in the trace event directory.
Packit Service 360c39
Packit Service 360c39
        @return: Returns the contents of the file "enable" in the trace event
Packit Service 360c39
        directory.
Packit Service 360c39
        @rtype: String
Packit Service 360c39
        """
Packit Service 360c39
        fileContents = self.__getEventPathItem(os.path.join(self.getPathToTraceEvent(), "enable"))
Packit Service 360c39
        if (len(fileContents) > 0):
Packit Service 360c39
            return fileContents[0].rstrip()
Packit Service 360c39
        else:
Packit Service 360c39
            return ""
Packit Service 360c39
Packit Service 360c39
    def getFilter(self):
Packit Service 360c39
        """
Packit Service 360c39
        Returns the contents of the file "filter" in the trace event
Packit Service 360c39
        directory. Each line in the file is appened to an array that will be
Packit Service 360c39
        returned.
Packit Service 360c39
Packit Service 360c39
        @return: Returns the contents of the file "filter" in the trace event
Packit Service 360c39
        directory.
Packit Service 360c39
        @rtype: Array
Packit Service 360c39
        """
Packit Service 360c39
        return self.__getEventPathItem(os.path.join(self.getPathToTraceEvent(), "filter"))
Packit Service 360c39
Packit Service 360c39
    def getFormat(self):
Packit Service 360c39
        """
Packit Service 360c39
        Returns the contents of the file "format" in the trace event
Packit Service 360c39
        directory. Each line in the file is appened to an array that will be
Packit Service 360c39
        returned.
Packit Service 360c39
Packit Service 360c39
        @return: Returns the contents of the file "format" in the trace event
Packit Service 360c39
        directory.
Packit Service 360c39
        @rtype: Array
Packit Service 360c39
        """
Packit Service 360c39
        return self.__getEventPathItem(os.path.join(self.getPathToTraceEvent(), "format"))
Packit Service 360c39
Packit Service 360c39
    def getID(self):
Packit Service 360c39
        """
Packit Service 360c39
        Returns the contents of the file "id" in the trace event directory.
Packit Service 360c39
Packit Service 360c39
        @return: Returns the contents of the file "id" in the trace event
Packit Service 360c39
        directory.
Packit Service 360c39
        @rtype: String
Packit Service 360c39
        """
Packit Service 360c39
        fileContents = self.__getEventPathItem(os.path.join(self.getPathToTraceEvent(), "id"))
Packit Service 360c39
        if (len(fileContents) > 0):
Packit Service 360c39
            return fileContents[0].rstrip()
Packit Service 360c39
        else:
Packit Service 360c39
            return ""
Packit Service 360c39
Packit Service 360c39
    def setEventEnable(self, eventEnableString):
Packit Service 360c39
        """
Packit Service 360c39
        Set the trace event to either enabled(1) or disabled(0) by writing to
Packit Service 360c39
        the trace event's "enable" file.
Packit Service 360c39
Packit Service 360c39
        @param eventEnableString: The value of the string should be 1 for
Packit Service 360c39
        enabled or 0 for disabled.
Packit Service 360c39
        @param eventEnableString: String
Packit Service 360c39
        """
Packit Service 360c39
        if ((eventEnableString == "0") or (eventEnableString == "1")):
Packit Service 360c39
            self.__setEventPathItem(os.path.join(self.getPathToTraceEvent(), "enable"), eventEnableString, appendToFile=False)
Packit Service 360c39
        else:
Packit Service 360c39
            message = "The trace event \"enable\" file only accepts the values of 0 or 1. The value %s will not be written: %s." %(eventEnableString)
Packit Service 360c39
            logging.getLogger(MAIN_LOGGER_NAME).error(message)
Packit Service 360c39
Packit Service 360c39
class TraceEvents:
Packit Service 360c39
    """
Packit Service 360c39
    A class that is a container for multiple trace events that are located in a
Packit Service 360c39
    directory.
Packit Service 360c39
    """
Packit Service 360c39
    def __init__(self, pathToTraceEvents):
Packit Service 360c39
        """
Packit Service 360c39
        @param pathToTraceEvents: The path to the directory that contains trace
Packit Service 360c39
        events.
Packit Service 360c39
        @type pathToTraceEvents: String
Packit Service 360c39
        """
Packit Service 360c39
        self.__pathToTraceEvents = pathToTraceEvents
Packit Service 360c39
        self.__traceEventsMap = self.__generateTraceEvents()
Packit Service 360c39
Packit Service 360c39
    def __generateTraceEvents(self):
Packit Service 360c39
        """
Packit Service 360c39
        Generates a map of all the trace events.
Packit Service 360c39
Packit Service 360c39
        @return: Returns a map of all the TraceEvent found.
Packit Service 360c39
        @rtype: Dict
Packit Service 360c39
        """
Packit Service 360c39
        traceEventsMap = {}
Packit Service 360c39
        if (not os.path.exists(self.__pathToTraceEvents)):
Packit Service 360c39
            message = "The path does not exist: %s" %(self.__pathToTraceEvents)
Packit Service 360c39
            logging.getLogger(MAIN_LOGGER_NAME).error(message)
Packit Service 360c39
            return traceEventsMap
Packit Service 360c39
        elif (os.path.isdir(self.__pathToTraceEvents)):
Packit Service 360c39
            dirlist = []
Packit Service 360c39
            try:
Packit Service 360c39
                dirlist = os.listdir(self.__pathToTraceEvents)
Packit Service 360c39
            except OSError:
Packit Service 360c39
                message = "There was error listing contents of the directory: %s" %(self.__pathToTraceEvents)
Packit Service 360c39
                logging.getLogger(MAIN_LOGGER_NAME).error(message)
Packit Service 360c39
            for item in dirlist:
Packit Service 360c39
                pathToItem = os.path.join(PATH_TO_GFS2_TRACE_EVENTS_DIR, item)
Packit Service 360c39
                if (os.path.isdir(pathToItem)):
Packit Service 360c39
                    traceEvent = TraceEvent(pathToItem)
Packit Service 360c39
                    traceEventsMap[traceEvent.getName()] = traceEvent
Packit Service 360c39
        return traceEventsMap
Packit Service 360c39
Packit Service 360c39
    def getPathToTraceEvents(self):
Packit Service 360c39
        """
Packit Service 360c39
        Returns the path to the directory that contains all the trace events.
Packit Service 360c39
Packit Service 360c39
        @return: Return the path to the directory that contains all the trace
Packit Service 360c39
        events.
Packit Service 360c39
        @rtype: String
Packit Service 360c39
        """
Packit Service 360c39
        return self.__pathToTraceEvents
Packit Service 360c39
Packit Service 360c39
    def getTraceEventNames(self):
Packit Service 360c39
        """
Packit Service 360c39
        Returns a list of all the trace event names found.
Packit Service 360c39
Packit Service 360c39
        @return: Returns a list of all the trace event names found.
Packit Service 360c39
        @rtype: Array
Packit Service 360c39
        """
Packit Service 360c39
        return list(self.__traceEventsMap.keys())
Packit Service 360c39
Packit Service 360c39
    def getTraceEvent(self, traceEventName):
Packit Service 360c39
        """
Packit Service 360c39
        Returns a TraceEvent that matches the traceEventName. If no match is
Packit Service 360c39
        found then None is returned.
Packit Service 360c39
Packit Service 360c39
        @return: Returns a TraceEvent that matches the traceEventName. If no
Packit Service 360c39
        match is found then None is returned.
Packit Service 360c39
        @rtype: TraceEvent
Packit Service 360c39
        """
Packit Service 360c39
        if (traceEventName in self.__traceEventsMap):
Packit Service 360c39
            return self.__traceEventsMap.get(traceEventName)
Packit Service 360c39
        return None
Packit Service 360c39
Packit Service 360c39
# #####################################################################
Packit Service 360c39
# Helper functions.
Packit Service 360c39
# #####################################################################
Packit Service 360c39
def runCommand(command, listOfCommandOptions, standardOut=subprocess.PIPE, standardError=subprocess.PIPE):
Packit Service 360c39
    """
Packit Service 360c39
    This function will execute a command. It will return True if the return code
Packit Service 360c39
    was zero, otherwise False is returned.
Packit Service 360c39
Packit Service 360c39
    @return: Returns True if the return code was zero, otherwise False is
Packit Service 360c39
    returned.
Packit Service 360c39
    @rtype: Boolean
Packit Service 360c39
Packit Service 360c39
    @param command: The command that will be executed.
Packit Service 360c39
    @type command: String
Packit Service 360c39
    @param listOfCommandOptions: The list of options for the command that will
Packit Service 360c39
    be executed.
Packit Service 360c39
    @type listOfCommandOptions: Array
Packit Service 360c39
    @param standardOut: The pipe that will be used to write standard output. By
Packit Service 360c39
    default the pipe that is used is subprocess.PIPE.
Packit Service 360c39
    @type standardOut: Pipe
Packit Service 360c39
    @param standardError: The pipe that will be used to write standard error. By
Packit Service 360c39
    default the pipe that is used is subprocess.PIPE.
Packit Service 360c39
    @type standardError: Pipe
Packit Service 360c39
    """
Packit Service 360c39
    stdout = ""
Packit Service 360c39
    stderr = ""
Packit Service 360c39
    try:
Packit Service 360c39
        commandList = [command]
Packit Service 360c39
        commandList += listOfCommandOptions
Packit Service 360c39
        task = subprocess.Popen(commandList, stdout=standardOut, stderr=standardError)
Packit Service 360c39
        task.wait()
Packit Service 360c39
        (stdout, stderr) = task.communicate()
Packit Service 360c39
        return (task.returncode == 0)
Packit Service 360c39
    except OSError:
Packit Service 360c39
        commandOptionString = ""
Packit Service 360c39
        for option in listOfCommandOptions:
Packit Service 360c39
            commandOptionString += "%s " %(option)
Packit Service 360c39
        message = "An error occurred running the command: $ %s %s\n" %(command, commandOptionString)
Packit Service 360c39
        if (len(stdout) > 0):
Packit Service 360c39
            message += stdout
Packit Service 360c39
        message += "\n"
Packit Service 360c39
        if (len(stderr) > 0):
Packit Service 360c39
            message += stderr
Packit Service 360c39
        logging.getLogger(MAIN_LOGGER_NAME).error(message)
Packit Service 360c39
    return False
Packit Service 360c39
Packit Service 360c39
def mountFilesystem(filesystemType, pathToDevice, pathToMountPoint):
Packit Service 360c39
    """
Packit Service 360c39
    This function will attempt to mount a filesystem. If the filesystem is
Packit Service 360c39
    already mounted or the filesystem was successfully mounted then True is
Packit Service 360c39
    returned, otherwise False is returned.
Packit Service 360c39
Packit Service 360c39
    @return: If the filesystem is already mounted or the filesystem was
Packit Service 360c39
    successfully mounted then True is returned, otherwise False is returned.
Packit Service 360c39
    @rtype: Boolean
Packit Service 360c39
Packit Service 360c39
    @param filesystemType: The type of filesystem that will be mounted.
Packit Service 360c39
    @type filesystemType: String
Packit Service 360c39
    @param pathToDevice: The path to the device that will be mounted.
Packit Service 360c39
    @type pathToDevice: String
Packit Service 360c39
    @param pathToMountPoint: The path to the directory that will be used as the
Packit Service 360c39
    mount point for the device.
Packit Service 360c39
    @type pathToMountPoint: String
Packit Service 360c39
    """
Packit Service 360c39
    if (os.path.ismount(PATH_TO_DEBUG_DIR)):
Packit Service 360c39
        return True
Packit Service 360c39
    listOfCommandOptions = ["-t", filesystemType, pathToDevice, pathToMountPoint]
Packit Service 360c39
    if (not runCommand("mount", listOfCommandOptions)):
Packit Service 360c39
        message = "There was an error mounting the filesystem type %s for the device %s to the mount point %s." %(filesystemType, pathToDevice, pathToMountPoint)
Packit Service 360c39
        logging.getLogger(MAIN_LOGGER_NAME).error(message)
Packit Service 360c39
    return  os.path.ismount(PATH_TO_DEBUG_DIR)
Packit Service 360c39
Packit Service 360c39
def exitScript(removePidFile=True, errorCode=0):
Packit Service 360c39
    """
Packit Service 360c39
    This function will cause the script to exit or quit. It will return an error
Packit Service 360c39
    code and will remove the pid file that was created.
Packit Service 360c39
Packit Service 360c39
    @param removePidFile: If True(default) then the pid file will be remove
Packit Service 360c39
    before the script exits.
Packit Service 360c39
    @type removePidFile: Boolean
Packit Service 360c39
    @param errorCode: The exit code that will be returned. The default value is 0.
Packit Service 360c39
    @type errorCode: Int
Packit Service 360c39
    """
Packit Service 360c39
    if (removePidFile):
Packit Service 360c39
        message = "Removing the pid file: %s" %(PATH_TO_PID_FILENAME)
Packit Service 360c39
        logging.getLogger(MAIN_LOGGER_NAME).debug(message)
Packit Service 360c39
        if (os.path.exists(PATH_TO_PID_FILENAME)):
Packit Service 360c39
            try:
Packit Service 360c39
                os.remove(PATH_TO_PID_FILENAME)
Packit Service 360c39
            except IOError:
Packit Service 360c39
                message = "There was an error removing the file: %s." %(PATH_TO_PID_FILENAME)
Packit Service 360c39
                logging.getLogger(MAIN_LOGGER_NAME).error(message)
Packit Service 360c39
    message = "The script will exit."
Packit Service 360c39
    logging.getLogger(MAIN_LOGGER_NAME).info(message)
Packit Service 360c39
    sys.exit(errorCode)
Packit Service 360c39
Packit Service 360c39
def getMountedGFS2Filesystems():
Packit Service 360c39
    """
Packit Service 360c39
    This function returns a list of all the mounted GFS2 filesystems.
Packit Service 360c39
Packit Service 360c39
    @return: Returns a list of all the mounted GFS2 filesystems.
Packit Service 360c39
    @rtype: Array
Packit Service 360c39
    """
Packit Service 360c39
    fsType = "gfs2"
Packit Service 360c39
    listOfMountedFilesystems = []
Packit Service 360c39
    dataOutput = FileUtils.getDataFromFile("/proc/mounts")
Packit Service 360c39
    if (not dataOutput == None):
Packit Service 360c39
        for line in dataOutput:
Packit Service 360c39
            splitLine = line.split()
Packit Service 360c39
            if (len(splitLine) > 0):
Packit Service 360c39
                if (splitLine[2] == fsType):
Packit Service 360c39
                    listOfMountedFilesystems.append(line)
Packit Service 360c39
    return listOfMountedFilesystems
Packit Service 360c39
# ##############################################################################
Packit Service 360c39
# Get user selected options
Packit Service 360c39
# ##############################################################################
Packit Service 360c39
def __getOptions(version) :
Packit Service 360c39
    """
Packit Service 360c39
    This function creates the OptionParser and returns commandline
Packit Service 360c39
    a tuple of the selected commandline options and commandline args.
Packit Service 360c39
Packit Service 360c39
    The cmdlineOpts which is the options user selected and cmdLineArgs
Packit Service 360c39
    is value passed and  not associated with an option.
Packit Service 360c39
Packit Service 360c39
    @return: A tuple of the selected commandline options and commandline args.
Packit Service 360c39
    @rtype: Tuple
Packit Service 360c39
Packit Service 360c39
    @param version: The version of the this script.
Packit Service 360c39
    @type version: String
Packit Service 360c39
    """
Packit Service 360c39
    cmdParser = OptionParserExtended(version)
Packit Service 360c39
    cmdParser.add_option("-d", "--debug",
Packit Service 360c39
                         action="store_true",
Packit Service 360c39
                         dest="enableDebugLogging",
Packit Service 360c39
                         help="enables debug logging",
Packit Service 360c39
                         default=False)
Packit Service 360c39
    cmdParser.add_option("-q", "--quiet",
Packit Service 360c39
                         action="store_true",
Packit Service 360c39
                         dest="disableLoggingToConsole",
Packit Service 360c39
                         help="disables logging to console",
Packit Service 360c39
                         default=False)
Packit Service 360c39
    cmdParser.add_option("-l", "--list",
Packit Service 360c39
                         action="store_true",
Packit Service 360c39
                         dest="listTraceEvents",
Packit Service 360c39
                         help="lists the enabled state and filters for the GFS2 trace events",
Packit Service 360c39
                         default=False)
Packit Service 360c39
    cmdParser.add_option("-E", "--enable_all_trace_events",
Packit Service 360c39
                         action="store_true",
Packit Service 360c39
                         dest="enableAllTraceEvents",
Packit Service 360c39
                         help="enables all trace_events for GFS2",
Packit Service 360c39
                         default=False)
Packit Service 360c39
    cmdParser.add_option("-e", "--enable_trace_event",
Packit Service 360c39
                         action="extend",
Packit Service 360c39
                         dest="enableTraceEventsList",
Packit Service 360c39
                         help="selected trace_events that will be enabled for GFS2",
Packit Service 360c39
                         type="string",
Packit Service 360c39
                         metavar="<trace event name>",
Packit Service 360c39
                         default=[])
Packit Service 360c39
    cmdParser.add_option("-N", "--disable_all_trace_events",
Packit Service 360c39
                         action="store_true",
Packit Service 360c39
                         dest="disableAllTraceEvents",
Packit Service 360c39
                         help="disables all trace_events for GFS2",
Packit Service 360c39
                         default=False)
Packit Service 360c39
    cmdParser.add_option("-n", "--disable_trace_event",
Packit Service 360c39
                         action="extend",
Packit Service 360c39
                         dest="disableTraceEventsList",
Packit Service 360c39
                         help="selected trace_events that will be disabled for GFS2",
Packit Service 360c39
                         type="string",
Packit Service 360c39
                         metavar="<trace event name>",
Packit Service 360c39
                         default=[])
Packit Service 360c39
    cmdParser.add_option("-c", "--capture",
Packit Service 360c39
                         action="store",
Packit Service 360c39
                         dest="pathToOutputFilename",
Packit Service 360c39
                         help="enables capturing of trace events and will save the data to a file",
Packit Service 360c39
                         type="string",
Packit Service 360c39
                         metavar="<output filename>",
Packit Service 360c39
                         default="")
Packit Service 360c39
Packit Service 360c39
    (cmdLineOpts, cmdLineArgs) = cmdParser.parse_args()
Packit Service 360c39
    return (cmdLineOpts, cmdLineArgs)
Packit Service 360c39
Packit Service 360c39
# ##############################################################################
Packit Service 360c39
# OptParse classes for commandline options
Packit Service 360c39
# ##############################################################################
Packit Service 360c39
class OptionParserExtended(OptionParser):
Packit Service 360c39
    """
Packit Service 360c39
    This is the class that gets the command line options the end user
Packit Service 360c39
    selects.
Packit Service 360c39
    """
Packit Service 360c39
    def __init__(self, version) :
Packit Service 360c39
        """
Packit Service 360c39
        @param version: The version of the this script.
Packit Service 360c39
        @type version: String
Packit Service 360c39
        """
Packit Service 360c39
        self.__commandName = os.path.basename(sys.argv[0])
Packit Service 360c39
        versionMessage = "%s %s\n" %(self.__commandName, version)
Packit Service 360c39
Packit Service 360c39
        commandDescription  ="%s can enable trace events, disable trace events, and capture data from GFS2 trace events.\n"%(self.__commandName)
Packit Service 360c39
        OptionParser.__init__(self, option_class=ExtendOption,
Packit Service 360c39
                              version=versionMessage,
Packit Service 360c39
                              description=commandDescription)
Packit Service 360c39
Packit Service 360c39
    def print_help(self):
Packit Service 360c39
        """
Packit Service 360c39
        Print examples at the bottom of the help message.
Packit Service 360c39
        """
Packit Service 360c39
        exampleMessage = "\nExamples:\n"
Packit Service 360c39
        exampleMessage += "To list the enable status and filter for each trace event.\n"
Packit Service 360c39
        exampleMessage += "# %s -l\n\n" %(self.__commandName)
Packit Service 360c39
        exampleMessage += "To disable all trace events.\n"
Packit Service 360c39
        exampleMessage += "# %s -N\n\n" %(self.__commandName)
Packit Service 360c39
        exampleMessage += "To enable all trace events.\n"
Packit Service 360c39
        exampleMessage += "# %s -E\n\n" %(self.__commandName)
Packit Service 360c39
        exampleMessage += "To disable all trace events and then enable a couple trace events.\n"
Packit Service 360c39
        exampleMessage += "# %s -N -e gfs2_demote_rq,gfs2_glock_state_change,gfs2_promote\n\n" %(self.__commandName)
Packit Service 360c39
        exampleMessage += "To capture all the trace events and write to the file /tmp/gfs2_trace.log.\n"
Packit Service 360c39
        exampleMessage += "# %s -c /tmp/gfs2_trace.log\n\n" %(self.__commandName)
Packit Service 360c39
        exampleMessage += "To disable all trace events and then enable a couple trace events and capture the output to a file.\n"
Packit Service 360c39
        exampleMessage += "# %s -N -e gfs2_demote_rq,gfs2_glock_state_change,gfs2_promote -c /tmp/gfs2_trace.log\n" %(self.__commandName)
Packit Service 360c39
        self.print_version()
Packit Service 360c39
        OptionParser.print_help(self)
Packit Service 360c39
        print(exampleMessage)
Packit Service 360c39
Packit Service 360c39
class ExtendOption (Option):
Packit Service 360c39
        """
Packit Service 360c39
        Allow to specify comma delimited list of entries for arrays
Packit Service 360c39
        and dictionaries.
Packit Service 360c39
        """
Packit Service 360c39
        ACTIONS = Option.ACTIONS + ("extend",)
Packit Service 360c39
        STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",)
Packit Service 360c39
        TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",)
Packit Service 360c39
Packit Service 360c39
        def take_action(self, action, dest, opt, value, values, parser):
Packit Service 360c39
            """
Packit Service 360c39
            This function is a wrapper to take certain options passed on command
Packit Service 360c39
            prompt and wrap them into an Array.
Packit Service 360c39
Packit Service 360c39
            @param action: The type of action that will be taken. For example:
Packit Service 360c39
            "store_true", "store_false", "extend".
Packit Service 360c39
            @type action: String
Packit Service 360c39
            @param dest: The name of the variable that will be used to store the
Packit Service 360c39
            option.
Packit Service 360c39
            @type dest: String/Boolean/Array
Packit Service 360c39
            @param opt: The option string that triggered the action.
Packit Service 360c39
            @type opt: String
Packit Service 360c39
            @param value: The value of opt(option) if it takes a
Packit Service 360c39
            value, if not then None.
Packit Service 360c39
            @type value:
Packit Service 360c39
            @param values: All the opt(options) in a dictionary.
Packit Service 360c39
            @type values: Dictionary
Packit Service 360c39
            @param parser: The option parser that was orginally called.
Packit Service 360c39
            @type parser: OptionParser
Packit Service 360c39
            """
Packit Service 360c39
            if (action == "extend") :
Packit Service 360c39
                valueList=[]
Packit Service 360c39
                try:
Packit Service 360c39
                    for v in value.split(","):
Packit Service 360c39
                        # Need to add code for dealing with paths if there is option for paths.
Packit Service 360c39
                        valueList.append(v)
Packit Service 360c39
                except:
Packit Service 360c39
                    pass
Packit Service 360c39
                else:
Packit Service 360c39
                    values.ensure_value(dest, []).extend(valueList)
Packit Service 360c39
            else:
Packit Service 360c39
                Option.take_action(self, action, dest, opt, value, values, parser)
Packit Service 360c39
Packit Service 360c39
# ###############################################################################
Packit Service 360c39
# Main Function
Packit Service 360c39
# ###############################################################################
Packit Service 360c39
if __name__ == "__main__":
Packit Service 360c39
    try:
Packit Service 360c39
        # #######################################################################
Packit Service 360c39
        # Get the options from the commandline.
Packit Service 360c39
        # #######################################################################
Packit Service 360c39
        (cmdLineOpts, cmdLineArgs) = __getOptions(VERSION_NUMBER)
Packit Service 360c39
Packit Service 360c39
        # #######################################################################
Packit Service 360c39
        # Setup the logger
Packit Service 360c39
        # #######################################################################
Packit Service 360c39
        # Create the logger
Packit Service 360c39
        logLevel = logging.INFO
Packit Service 360c39
        logger = logging.getLogger(MAIN_LOGGER_NAME)
Packit Service 360c39
        logger.setLevel(logLevel)
Packit Service 360c39
        # Create a new status function and level.
Packit Service 360c39
        logging.STATUS = logging.INFO + 2
Packit Service 360c39
        logging.addLevelName(logging.STATUS, "STATUS")
Packit Service 360c39
        # Create a function for the STATUS_LEVEL since not defined by python. This
Packit Service 360c39
        # means you can call it like the other predefined message
Packit Service 360c39
        # functions. Example: logging.getLogger("loggerName").status(message)
Packit Service 360c39
        setattr(logger, "status", lambda *args: logger.log(logging.STATUS, *args))
Packit Service 360c39
        streamHandler = logging.StreamHandler()
Packit Service 360c39
        streamHandler.setFormatter(logging.Formatter("%(levelname)s %(message)s"))
Packit Service 360c39
        logger.addHandler(streamHandler)
Packit Service 360c39
Packit Service 360c39
        # Set options on logger for debugging or no logging.
Packit Service 360c39
        if (cmdLineOpts.disableLoggingToConsole):
Packit Service 360c39
            logging.disable(logging.CRITICAL)
Packit Service 360c39
        elif (cmdLineOpts.enableDebugLogging) :
Packit Service 360c39
            logging.getLogger(MAIN_LOGGER_NAME).setLevel(logging.DEBUG)
Packit Service 360c39
            message = "Debugging has been enabled."
Packit Service 360c39
            logging.getLogger(MAIN_LOGGER_NAME).debug(message)
Packit Service 360c39
Packit Service 360c39
        # #######################################################################
Packit Service 360c39
        # Check to see if pid file exists and error if it does.
Packit Service 360c39
        # #######################################################################
Packit Service 360c39
        if (os.path.exists(PATH_TO_PID_FILENAME)):
Packit Service 360c39
            message = "The PID file %s already exists and this script cannot run till it does not exist." %(PATH_TO_PID_FILENAME)
Packit Service 360c39
            logging.getLogger(MAIN_LOGGER_NAME).error(message)
Packit Service 360c39
            message = "Verify that there are no other existing processes running. If there are running processes those need to be stopped first and the file removed."
Packit Service 360c39
            logging.getLogger(MAIN_LOGGER_NAME).info(message)
Packit Service 360c39
            exitScript(removePidFile=False, errorCode=1)
Packit Service 360c39
        else:
Packit Service 360c39
            message = "Creating the pid file: %s" %(PATH_TO_PID_FILENAME)
Packit Service 360c39
            logging.getLogger(MAIN_LOGGER_NAME).debug(message)
Packit Service 360c39
            # Creata the pid file so we dont have more than 1 process of this
Packit Service 360c39
            # script running.
Packit Service 360c39
            FileUtils.writeToFile(PATH_TO_PID_FILENAME, str(os.getpid()), createFile=True)
Packit Service 360c39
Packit Service 360c39
        # #######################################################################
Packit Service 360c39
        # Check to see if there any GFS2 filesystems mounted, if not then exit.
Packit Service 360c39
        # #######################################################################
Packit Service 360c39
        if (not len(getMountedGFS2Filesystems()) > 0):
Packit Service 360c39
            message = "There was no GFS2 file-systems mounted."
Packit Service 360c39
            logging.getLogger(MAIN_LOGGER_NAME).info(message)
Packit Service 360c39
            exitScript(errorCode=1)
Packit Service 360c39
Packit Service 360c39
        # #######################################################################
Packit Service 360c39
        # Check to see if the debug directory is mounted. If not then
Packit Service 360c39
        # log an error.
Packit Service 360c39
        # #######################################################################
Packit Service 360c39
        if(mountFilesystem("debugfs", "none", PATH_TO_DEBUG_DIR)):
Packit Service 360c39
            message = "The debug filesystem %s is mounted." %(PATH_TO_DEBUG_DIR)
Packit Service 360c39
            logging.getLogger(MAIN_LOGGER_NAME).debug(message)
Packit Service 360c39
        else:
Packit Service 360c39
            message = "There was a problem mounting the debug filesystem: %s" %(PATH_TO_DEBUG_DIR)
Packit Service 360c39
            logging.getLogger(MAIN_LOGGER_NAME).error(message)
Packit Service 360c39
            message = "The debug filesystem is required to be mounted for this script to run."
Packit Service 360c39
            logging.getLogger(MAIN_LOGGER_NAME).info(message)
Packit Service 360c39
            exitScript(errorCode=1)
Packit Service 360c39
Packit Service 360c39
        # #######################################################################
Packit Service 360c39
        # List of the enable state and filters for each trace event
Packit Service 360c39
        # #######################################################################
Packit Service 360c39
        traceEvents = TraceEvents(PATH_TO_GFS2_TRACE_EVENTS_DIR)
Packit Service 360c39
        listOfTraceEventNames = traceEvents.getTraceEventNames()
Packit Service 360c39
Packit Service 360c39
        if (cmdLineOpts.listTraceEvents):
Packit Service 360c39
            listOfTraceEventNames.sort()
Packit Service 360c39
            maxTraceEventNameSize = len(max(listOfTraceEventNames, key=len))
Packit Service 360c39
            traceEventsString = ""
Packit Service 360c39
            for traceEventName in listOfTraceEventNames:
Packit Service 360c39
                traceEvent = traceEvents.getTraceEvent(traceEventName)
Packit Service 360c39
                if (not traceEventName == None):
Packit Service 360c39
                    traceEventEnableStatus = "UNKNOWN"
Packit Service 360c39
                    if (traceEvent.getEnable() == "0"):
Packit Service 360c39
                        traceEventEnableStatus = "DISABLED"
Packit Service 360c39
                    elif (traceEvent.getEnable() == "1"):
Packit Service 360c39
                        traceEventEnableStatus = "ENABLED"
Packit Service 360c39
                    whitespaces = ""
Packit Service 360c39
                    for i in range(0, (maxTraceEventNameSize - len(traceEventName))):
Packit Service 360c39
                        whitespaces += " "
Packit Service 360c39
                    traceEventsString += "%s    %s%s\n" %(traceEventName, whitespaces, traceEventEnableStatus)
Packit Service 360c39
            # Disable logging to console except for debug when we print into information to console.
Packit Service 360c39
            logging.disable(logging.CRITICAL)
Packit Service 360c39
            if (len(traceEventsString) > 0):
Packit Service 360c39
                print("trace event name           trace event status")
Packit Service 360c39
                print("----------------           ------------------")
Packit Service 360c39
                print(traceEventsString.rstrip())
Packit Service 360c39
            exitScript()
Packit Service 360c39
        # #######################################################################
Packit Service 360c39
        # Enable or Disable Trace Events
Packit Service 360c39
        # #######################################################################
Packit Service 360c39
        if (cmdLineOpts.disableAllTraceEvents):
Packit Service 360c39
            message = "Disabling all trace events."
Packit Service 360c39
            logging.getLogger(MAIN_LOGGER_NAME).info(message)
Packit Service 360c39
            for traceEventName in listOfTraceEventNames:
Packit Service 360c39
                traceEvent = traceEvents.getTraceEvent(traceEventName)
Packit Service 360c39
                if (not traceEvent == None):
Packit Service 360c39
                    traceEvent.setEventEnable("0")
Packit Service 360c39
        elif (cmdLineOpts.enableAllTraceEvents):
Packit Service 360c39
            message = "Enabling all trace events."
Packit Service 360c39
            logging.getLogger(MAIN_LOGGER_NAME).info(message)
Packit Service 360c39
            for traceEventName in listOfTraceEventNames:
Packit Service 360c39
                traceEvent = traceEvents.getTraceEvent(traceEventName)
Packit Service 360c39
                if (not traceEvent == None):
Packit Service 360c39
                    traceEvent.setEventEnable("1")
Packit Service 360c39
Packit Service 360c39
        if (len(cmdLineOpts.disableTraceEventsList) > 0):
Packit Service 360c39
            for traceEventName in cmdLineOpts.disableTraceEventsList:
Packit Service 360c39
                traceEvent = traceEvents.getTraceEvent(traceEventName)
Packit Service 360c39
                if (not traceEvent == None):
Packit Service 360c39
                    message = "Disabling the selected trace event: %s" %(traceEvent.getName())
Packit Service 360c39
                    logging.getLogger(MAIN_LOGGER_NAME).info(message)
Packit Service 360c39
                    traceEvent.setEventEnable("0")
Packit Service 360c39
        if (len(cmdLineOpts.enableTraceEventsList) > 0):
Packit Service 360c39
            for traceEventName in cmdLineOpts.enableTraceEventsList:
Packit Service 360c39
                traceEvent = traceEvents.getTraceEvent(traceEventName)
Packit Service 360c39
                if (not traceEvent == None):
Packit Service 360c39
                    message = "Enabling the selected trace event: %s" %(traceEvent.getName())
Packit Service 360c39
                    logging.getLogger(MAIN_LOGGER_NAME).info(message)
Packit Service 360c39
                    traceEvent.setEventEnable("1")
Packit Service 360c39
Packit Service 360c39
        # #######################################################################
Packit Service 360c39
        # Capture the data generate by the trace events.
Packit Service 360c39
        # #######################################################################
Packit Service 360c39
        if (len(cmdLineOpts.pathToOutputFilename) > 0):
Packit Service 360c39
            # Read from tracing pipe and write the output to a file.
Packit Service 360c39
            message = "The capturing of the trace events that were enabled to a file will be started by reading the the trace pipe: %s." %(PATH_TO_TRACE_PIPE)
Packit Service 360c39
            logging.getLogger(MAIN_LOGGER_NAME).info(message)
Packit Service 360c39
            message = "Leave this script running until you have capture all the data, then hit control-c to exit."
Packit Service 360c39
            logging.getLogger(MAIN_LOGGER_NAME).info(message)
Packit Service 360c39
            try:
Packit Service 360c39
                fout = open(cmdLineOpts.pathToOutputFilename, "w")
Packit Service 360c39
                for line in fileinput.input(PATH_TO_TRACE_PIPE):
Packit Service 360c39
                    fout.write(line)
Packit Service 360c39
                fout.close()
Packit Service 360c39
                message = "The data was written to this file: %s" %(cmdLineOpts.pathToOutputFilename)
Packit Service 360c39
                logging.getLogger(MAIN_LOGGER_NAME).info(message)
Packit Service 360c39
            except KeyboardInterrupt:
Packit Service 360c39
                message = "A control-c was detected and the capturing of trace events data will stop."
Packit Service 360c39
                logging.getLogger(MAIN_LOGGER_NAME).info(message)
Packit Service 360c39
                fout.close()
Packit Service 360c39
                message = "The data was written to this file: %s" %(cmdLineOpts.pathToOutputFilename)
Packit Service 360c39
                logging.getLogger(MAIN_LOGGER_NAME).info(message)
Packit Service 360c39
            except UnicodeEncodeError as e:
Packit Service 360c39
                message = "There was a unicode encode error writing to the file: %s." %(cmdLineOpts.pathToOutputFilename)
Packit Service 360c39
                logging.getLogger(MAIN_LOGGER_NAME).error(message)
Packit Service 360c39
            except IOError:
Packit Service 360c39
                message = "There was an error writing to the file: %s." %(cmdLineOpts.pathToOutputFilename)
Packit Service 360c39
                logging.getLogger(MAIN_LOGGER_NAME).error(message)
Packit Service 360c39
            message = "The capturing of the trace event data has completed."
Packit Service 360c39
            logging.getLogger(MAIN_LOGGER_NAME).info(message)
Packit Service 360c39
            # Compress the file so that it will have a smaller file size.
Packit Service 360c39
            pathToTarFilename = "%s.tar.bz2" %(os.path.splitext(cmdLineOpts.pathToOutputFilename)[0])
Packit Service 360c39
            message = "Creating a compressed archvied file: %s" %(pathToTarFilename)
Packit Service 360c39
            logging.getLogger(MAIN_LOGGER_NAME).info(message)
Packit Service 360c39
            try:
Packit Service 360c39
                tar = tarfile.open(pathToTarFilename, "w:bz2")
Packit Service 360c39
                tar.add(cmdLineOpts.pathToOutputFilename, arcname=os.path.basename(cmdLineOpts.pathToOutputFilename))
Packit Service 360c39
                tar.close()
Packit Service 360c39
                message = "The compressed archvied file was created: %s" %(pathToTarFilename)
Packit Service 360c39
                logging.getLogger(MAIN_LOGGER_NAME).info(message)
Packit Service 360c39
            except tarfile.TarError:
Packit Service 360c39
                message = "There was an error creating the tarfile: %s." %(pathToTarFilename)
Packit Service 360c39
                logging.getLogger(MAIN_LOGGER_NAME).error(message)
Packit Service 360c39
    except KeyboardInterrupt:
Packit Service 360c39
        print("")
Packit Service 360c39
        message =  "This script will exit since control-c was executed by end user."
Packit Service 360c39
        logging.getLogger(MAIN_LOGGER_NAME).error(message)
Packit Service 360c39
        exitScript()
Packit Service 360c39
    # #######################################################################
Packit Service 360c39
    # Exit the application with zero exit code since we cleanly exited.
Packit Service 360c39
    # #######################################################################
Packit Service 360c39
    exitScript()