|
Packit Service |
360c39 |
#!/usr/bin/python
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
The script "gfs2_lockcapture" will capture locking information from GFS2 file
|
|
Packit Service |
360c39 |
systems and DLM.
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@author : Shane Bradley
|
|
Packit Service |
360c39 |
@contact : sbradley@redhat.com
|
|
Packit Service |
360c39 |
@version : 0.95
|
|
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 logging.handlers
|
|
Packit Service |
360c39 |
from optparse import OptionParser, Option, SUPPRESS_HELP
|
|
Packit Service |
360c39 |
import time
|
|
Packit Service |
360c39 |
import platform
|
|
Packit Service |
360c39 |
import shutil
|
|
Packit Service |
360c39 |
import subprocess
|
|
Packit Service |
360c39 |
import tarfile
|
|
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 |
"""
|
|
Packit Service |
360c39 |
VERSION_NUMBER = "0.9-8"
|
|
Packit Service |
360c39 |
MAIN_LOGGER_NAME = "%s" %(os.path.basename(sys.argv[0]))
|
|
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 |
|
|
Packit Service |
360c39 |
# #####################################################################
|
|
Packit Service |
360c39 |
# Class to define what a clusternode is.
|
|
Packit Service |
360c39 |
# #####################################################################
|
|
Packit Service |
360c39 |
class ClusterNode:
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
This class represents a cluster node that is a current member in a cluster.
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
def __init__(self, clusternodeName, clusternodeID, clusterName, mapOfMountedFilesystemLabels):
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
@param clusternodeName: The name of the cluster node.
|
|
Packit Service |
360c39 |
@type clusternodeName: String
|
|
Packit Service |
360c39 |
@param clusterName: The name of the cluster that this cluster node is a
|
|
Packit Service |
360c39 |
member of.
|
|
Packit Service |
360c39 |
@param clusternodeID: The id of the cluster node.
|
|
Packit Service |
360c39 |
@type clusternodeID: Int
|
|
Packit Service |
360c39 |
@param clusterName: The name of the cluster that this cluster node is a
|
|
Packit Service |
360c39 |
@type clusterName: String
|
|
Packit Service |
360c39 |
@param mapOfMountedFilesystemLabels: A map of filesystem labels(key) for
|
|
Packit Service |
360c39 |
a mounted filesystem. The value is the line for the matching mounted
|
|
Packit Service |
360c39 |
filesystem from the mount -l command.
|
|
Packit Service |
360c39 |
@type mapOfMountedFilesystemLabels: Dict
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
self.__clusternodeName = clusternodeName
|
|
Packit Service |
360c39 |
self.__clusternodeID = clusternodeID
|
|
Packit Service |
360c39 |
self.__clusterName = clusterName
|
|
Packit Service |
360c39 |
self.__mapOfMountedFilesystemLabels = mapOfMountedFilesystemLabels
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
def __str__(self):
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
This function will return a string representation of the object.
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@return: Returns a string representation of the object.
|
|
Packit Service |
360c39 |
@rtype: String
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
rString = ""
|
|
Packit Service |
360c39 |
rString += "%s:%s(id:%d)" %(self.getClusterName(), self.getClusterNodeName(), self.getClusterNodeID())
|
|
Packit Service |
360c39 |
fsLabels = list(self.__mapOfMountedFilesystemLabels.keys())
|
|
Packit Service |
360c39 |
fsLabels.sort()
|
|
Packit Service |
360c39 |
for fsLabel in fsLabels:
|
|
Packit Service |
360c39 |
rString += "\n\t%s --> %s" %(fsLabel, self.__mapOfMountedFilesystemLabels.get(fsLabel))
|
|
Packit Service |
360c39 |
return rString.rstrip()
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
def getClusterNodeName(self):
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
Returns the name of the cluster node.
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@return: Returns the name of the cluster node.
|
|
Packit Service |
360c39 |
@rtype: String
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
return self.__clusternodeName
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
def getClusterNodeID(self):
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
Returns the id of the cluster node.
|
|
Packit Service |
360c39 |
@return: Returns the id of the cluster node.
|
|
Packit Service |
360c39 |
@rtype: String
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
return self.__clusternodeID
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
def getClusterName(self):
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
Returns the name of cluster that this cluster node is a member of.
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@return: Returns the name of cluster that this cluster node is a member
|
|
Packit Service |
360c39 |
of.
|
|
Packit Service |
360c39 |
@rtype: String
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
return self.__clusterName
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
def getMountedGFS2FilesystemNames(self, includeClusterName=True):
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
Returns the names of all the mounted GFS2 filesystems. By default
|
|
Packit Service |
360c39 |
includeClusterName is True which will include the name of the cluster
|
|
Packit Service |
360c39 |
and the GFS2 filesystem name(ex. f18cluster:mygfs2vol1) in the list of
|
|
Packit Service |
360c39 |
mounted GFS2 filesystems. If includeClusterName is False it will only
|
|
Packit Service |
360c39 |
return a list of all the mounted GFS2 filesystem names(ex. mygfs2vol1).
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@return: Returns a list of all the mounted GFS2 filesystem names.
|
|
Packit Service |
360c39 |
@rtype: Array
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@param includeClusterName: By default this option is True and will
|
|
Packit Service |
360c39 |
include the name of the cluster and the GFS2 filesystem name. If False
|
|
Packit Service |
360c39 |
then only the GFS2 filesystem name will be included.
|
|
Packit Service |
360c39 |
@param includeClusterName: Boolean
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
# If true will prepend the cluster name to gfs2 fs name
|
|
Packit Service |
360c39 |
if (includeClusterName):
|
|
Packit Service |
360c39 |
return list(self.__mapOfMountedFilesystemLabels.keys())
|
|
Packit Service |
360c39 |
else:
|
|
Packit Service |
360c39 |
listOfGFS2MountedFilesystemLabels = []
|
|
Packit Service |
360c39 |
for fsLabel in list(self.__mapOfMountedFilesystemLabels.keys()):
|
|
Packit Service |
360c39 |
fsLabelSplit = fsLabel.split(":", 1)
|
|
Packit Service |
360c39 |
if (len(fsLabelSplit) == 2):
|
|
Packit Service |
360c39 |
listOfGFS2MountedFilesystemLabels.append(fsLabelSplit[1])
|
|
Packit Service |
360c39 |
return listOfGFS2MountedFilesystemLabels
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
def getMountedGFS2FilesystemPaths(self):
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
Returns a map of all the mounted GFS2 filesystem paths. The key is the
|
|
Packit Service |
360c39 |
GFS2 fs name(clustername:fs name) and value is the mountpoint.
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@return: Returns a map of all the mounted GFS2 filesystem paths. The key
|
|
Packit Service |
360c39 |
is the GFS2 fs name(clustername:fs name) and value is the mountpoint.
|
|
Packit Service |
360c39 |
Returns a list of all the mounted GFS2 filesystem paths.
|
|
Packit Service |
360c39 |
@rtype: Map
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
mapOfGFS2MountedFilesystemPaths = {}
|
|
Packit Service |
360c39 |
for fsLabel in list(self.__mapOfMountedFilesystemLabels.keys()):
|
|
Packit Service |
360c39 |
value = self.__mapOfMountedFilesystemLabels.get(fsLabel)
|
|
Packit Service |
360c39 |
mountPoint = value.split("type", 1)[0].split("on")[1]
|
|
Packit Service |
360c39 |
if (len(mountPoint) > 0):
|
|
Packit Service |
360c39 |
mapOfGFS2MountedFilesystemPaths[fsLabel] = mountPoint
|
|
Packit Service |
360c39 |
return mapOfGFS2MountedFilesystemPaths
|
|
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" %(command, commandOptionString)
|
|
Packit Service |
360c39 |
if (len(stdout.rstrip()) > 0):
|
|
Packit Service |
360c39 |
message += "\n%s" %(stdout.rstrip())
|
|
Packit Service |
360c39 |
if (len(stderr.rstrip()) > 0):
|
|
Packit Service |
360c39 |
message += "\n%s" %(stderr.rstrip())
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
return False
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
def runCommandOutput(command, listOfCommandOptions, standardOut=subprocess.PIPE, standardError=subprocess.PIPE):
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
This function will execute a command. Returns the output that was written to standard output. None is
|
|
Packit Service |
360c39 |
returned if there was an error.
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@return: Returns the output that was written to standard output. None is
|
|
Packit Service |
360c39 |
returned if there was an error.
|
|
Packit Service |
360c39 |
@rtype: String
|
|
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 |
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" %(command, commandOptionString)
|
|
Packit Service |
360c39 |
if (len(stdout.rstrip()) > 0):
|
|
Packit Service |
360c39 |
message += "\n%s" %(stdout.rstrip())
|
|
Packit Service |
360c39 |
if (len(stderr.rstrip()) > 0):
|
|
Packit Service |
360c39 |
message += "\n%s" %(stderr.rstrip())
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
return None
|
|
Packit Service |
360c39 |
return stdout.decode().strip().rstrip()
|
|
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 |
|
|
Packit Service |
360c39 |
def mkdirs(pathToDSTDir):
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
This function will attempt to create a directory with the path of the value of pathToDSTDir.
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@return: Returns True if the directory was created or already exists.
|
|
Packit Service |
360c39 |
@rtype: Boolean
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@param pathToDSTDir: The path to the directory that will be created.
|
|
Packit Service |
360c39 |
@type pathToDSTDir: String
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
if (os.path.isdir(pathToDSTDir)):
|
|
Packit Service |
360c39 |
return True
|
|
Packit Service |
360c39 |
elif ((not os.access(pathToDSTDir, os.F_OK)) and (len(pathToDSTDir) > 0)):
|
|
Packit Service |
360c39 |
try:
|
|
Packit Service |
360c39 |
os.makedirs(pathToDSTDir)
|
|
Packit Service |
360c39 |
except (OSError, os.error):
|
|
Packit Service |
360c39 |
message = "Could not create the directory: %s." %(pathToDSTDir)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
return False
|
|
Packit Service |
360c39 |
except (IOError, os.error):
|
|
Packit Service |
360c39 |
message = "Could not create the directory with the path: %s." %(pathToDSTDir)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
return False
|
|
Packit Service |
360c39 |
return os.path.isdir(pathToDSTDir)
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
def removePIDFile():
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
This function will remove the pid file.
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@return: Returns True if the file was successfully remove or does not exist,
|
|
Packit Service |
360c39 |
otherwise False is returned.
|
|
Packit Service |
360c39 |
@rtype: Boolean
|
|
Packit Service |
360c39 |
"""
|
|
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 |
return os.path.exists(PATH_TO_PID_FILENAME)
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
def archiveData(pathToSrcDir):
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
This function will return the path to the tar.bz2 file that was created. If
|
|
Packit Service |
360c39 |
the tar.bz2 file failed to be created then an empty string will be returned
|
|
Packit Service |
360c39 |
which would indicate an error occurred.
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@return: This function will return the path to the tar.bz2 file that was
|
|
Packit Service |
360c39 |
created. If the tar.bz2 file failed to be created then an empty string will
|
|
Packit Service |
360c39 |
be returned which would indicate an error occurred.
|
|
Packit Service |
360c39 |
@rtype: String
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@param pathToSrcDir: The path to the directory that will be archived into a
|
|
Packit Service |
360c39 |
.tar.bz2 file.
|
|
Packit Service |
360c39 |
@type pathToSrcDir: String
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
if (os.path.exists(pathToSrcDir)):
|
|
Packit Service |
360c39 |
pathToTarFilename = "%s-%s.tar.bz2" %(pathToSrcDir, platform.node())
|
|
Packit Service |
360c39 |
if (os.path.exists(pathToTarFilename)):
|
|
Packit Service |
360c39 |
message = "A compressed archvied file already exists and will be removed: %s" %(pathToTarFilename)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).status(message)
|
|
Packit Service |
360c39 |
try:
|
|
Packit Service |
360c39 |
os.remove(pathToTarFilename)
|
|
Packit Service |
360c39 |
except IOError:
|
|
Packit Service |
360c39 |
message = "There was an error removing the file: %s." %(pathToTarFilename)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
return ""
|
|
Packit Service |
360c39 |
message = "Creating a compressed archvied file: %s" %(pathToTarFilename)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).status(message)
|
|
Packit Service |
360c39 |
try:
|
|
Packit Service |
360c39 |
tar = tarfile.open(pathToTarFilename, "w:bz2")
|
|
Packit Service |
360c39 |
tar.add(pathToSrcDir, arcname=os.path.basename(pathToSrcDir))
|
|
Packit Service |
360c39 |
tar.close()
|
|
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 |
return ""
|
|
Packit Service |
360c39 |
if (os.path.exists(pathToTarFilename)):
|
|
Packit Service |
360c39 |
return pathToTarFilename
|
|
Packit Service |
360c39 |
return ""
|
|
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 |
|
|
Packit Service |
360c39 |
def copyFile(pathToSrcFile, pathToDstFile):
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
This function will copy a src file to dst file.
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@return: Returns True if the file was copied successfully.
|
|
Packit Service |
360c39 |
@rtype: Boolean
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@param pathToSrcFile: The path to the source file that will be copied.
|
|
Packit Service |
360c39 |
@type pathToSrcFile: String
|
|
Packit Service |
360c39 |
@param pathToDstFile: The path to the destination of the file.
|
|
Packit Service |
360c39 |
@type pathToDstFile: String
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
if(not os.path.exists(pathToSrcFile)):
|
|
Packit Service |
360c39 |
message = "The file does not exist with the path: %s." %(pathToSrcFile)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
return False
|
|
Packit Service |
360c39 |
elif (not os.path.isfile(pathToSrcFile)):
|
|
Packit Service |
360c39 |
message = "The path to the source file is not a regular file: %s." %(pathToSrcFile)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
return False
|
|
Packit Service |
360c39 |
elif (pathToSrcFile == pathToDstFile):
|
|
Packit Service |
360c39 |
message = "The path to the source file and path to destination file cannot be the same: %s." %(pathToDstFile)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
return False
|
|
Packit Service |
360c39 |
else:
|
|
Packit Service |
360c39 |
# Create the directory structure if it does not exist.
|
|
Packit Service |
360c39 |
(head, tail) = os.path.split(pathToDstFile)
|
|
Packit Service |
360c39 |
if (not mkdirs(head)) :
|
|
Packit Service |
360c39 |
# The path to the directory was not created so file
|
|
Packit Service |
360c39 |
# could not be copied.
|
|
Packit Service |
360c39 |
return False
|
|
Packit Service |
360c39 |
# Copy the file to the dst path.
|
|
Packit Service |
360c39 |
try:
|
|
Packit Service |
360c39 |
shutil.copy(pathToSrcFile, pathToDstFile)
|
|
Packit Service |
360c39 |
except shutil.Error:
|
|
Packit Service |
360c39 |
message = "Cannot copy the file %s to %s." %(pathToSrcFile, pathToDstFile)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
return False
|
|
Packit Service |
360c39 |
except OSError:
|
|
Packit Service |
360c39 |
message = "Cannot copy the file %s to %s." %(pathToSrcFile, pathToDstFile)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
return False
|
|
Packit Service |
360c39 |
except IOError:
|
|
Packit Service |
360c39 |
message = "Cannot copy the file %s to %s." %(pathToSrcFile, pathToDstFile)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
return False
|
|
Packit Service |
360c39 |
return (os.path.exists(pathToDstFile))
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
def copyDirectory(pathToSrcDir, pathToDstDir):
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
This function will copy a src dir to dst dir.
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@return: Returns True if the dir was copied successfully.
|
|
Packit Service |
360c39 |
@rtype: Boolean
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@param pathToSrcDir: The path to the source dir that will be copied.
|
|
Packit Service |
360c39 |
@type pathToSrcDir: String
|
|
Packit Service |
360c39 |
@param pathToDstDir: The path to the destination of the dir.
|
|
Packit Service |
360c39 |
@type pathToDstDir: String
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
if(not os.path.exists(pathToSrcDir)):
|
|
Packit Service |
360c39 |
message = "The directory does not exist with the path: %s." %(pathToSrcDir)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
return False
|
|
Packit Service |
360c39 |
elif (not os.path.isdir(pathToSrcDir)):
|
|
Packit Service |
360c39 |
message = "The path to the source directory is not a directory: %s." %(pathToSrcDir)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
return False
|
|
Packit Service |
360c39 |
elif (pathToSrcDir == pathToDstDir):
|
|
Packit Service |
360c39 |
message = "The path to the source directory and path to destination directory cannot be the same: %s." %(pathToDstDir)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
return False
|
|
Packit Service |
360c39 |
else:
|
|
Packit Service |
360c39 |
if (not mkdirs(pathToDstDir)) :
|
|
Packit Service |
360c39 |
# The path to the directory was not created so file
|
|
Packit Service |
360c39 |
# could not be copied.
|
|
Packit Service |
360c39 |
return False
|
|
Packit Service |
360c39 |
# Copy the file to the dst path.
|
|
Packit Service |
360c39 |
dst = os.path.join(pathToDstDir, os.path.basename(pathToSrcDir))
|
|
Packit Service |
360c39 |
try:
|
|
Packit Service |
360c39 |
shutil.copytree(pathToSrcDir, dst)
|
|
Packit Service |
360c39 |
except shutil.Error:
|
|
Packit Service |
360c39 |
message = "Cannot copy the directory %s to %s." %(pathToSrcDir, dst)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
return False
|
|
Packit Service |
360c39 |
except OSError:
|
|
Packit Service |
360c39 |
message = "Cannot copy the directory %s to %s." %(pathToSrcDir, dst)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
return False
|
|
Packit Service |
360c39 |
except IOError:
|
|
Packit Service |
360c39 |
message = "Cannot copy the directory %s to %s." %(pathToSrcDir, dst)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
return False
|
|
Packit Service |
360c39 |
return (os.path.exists(dst))
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
def backupOutputDirectory(pathToOutputDir):
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
This function will return True if the pathToOutputDir does not exist or the
|
|
Packit Service |
360c39 |
directory was successfully rename. If pathToOutputDir exists and was not
|
|
Packit Service |
360c39 |
successfully rename then False is returned.
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@return: Returns True if the pathToOutputDir does not exist or the directory
|
|
Packit Service |
360c39 |
was successfully rename. If pathToOutputDir exists and was not successfully
|
|
Packit Service |
360c39 |
rename then False is returned.
|
|
Packit Service |
360c39 |
@rtype: Boolean
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@param pathToOutputDir: The path to the directory that will be backed up.
|
|
Packit Service |
360c39 |
@type pathToOutputDir: String
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
if (os.path.exists(pathToOutputDir)):
|
|
Packit Service |
360c39 |
message = "The path already exists and could contain previous lockdump data: %s" %(pathToOutputDir)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).info(message)
|
|
Packit Service |
360c39 |
backupIndex = 1
|
|
Packit Service |
360c39 |
pathToDST = ""
|
|
Packit Service |
360c39 |
keepSearchingForIndex = True
|
|
Packit Service |
360c39 |
while (keepSearchingForIndex):
|
|
Packit Service |
360c39 |
pathToDST = "%s.bk-%d" %(pathToOutputDir, backupIndex)
|
|
Packit Service |
360c39 |
if (os.path.exists(pathToDST)):
|
|
Packit Service |
360c39 |
backupIndex += 1
|
|
Packit Service |
360c39 |
else:
|
|
Packit Service |
360c39 |
keepSearchingForIndex = False
|
|
Packit Service |
360c39 |
try:
|
|
Packit Service |
360c39 |
message = "The existing output directory will be renamed: %s to %s." %(pathToOutputDir, pathToDST)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).status(message)
|
|
Packit Service |
360c39 |
shutil.move(pathToOutputDir, pathToDST)
|
|
Packit Service |
360c39 |
except shutil.Error:
|
|
Packit Service |
360c39 |
message = "There was an error renaming the directory: %s to %s." %(pathToOutputDir, pathToDST)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
except OSError:
|
|
Packit Service |
360c39 |
message = "There was an error renaming the directory: %s to %s." %(pathToOutputDir, pathToDST)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
# The path should not exists now, else there was an error backing up an
|
|
Packit Service |
360c39 |
# existing output directory.
|
|
Packit Service |
360c39 |
return (not os.path.exists(pathToOutputDir))
|
|
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 |
removePIDFile()
|
|
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 |
# #####################################################################
|
|
Packit Service |
360c39 |
# Helper functions for gathering the lockdumps.
|
|
Packit Service |
360c39 |
# #####################################################################
|
|
Packit Service |
360c39 |
def getClusterNode(listOfGFS2Names):
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
This function return a ClusterNode object if the machine is a member of a
|
|
Packit Service |
360c39 |
cluster and has GFS2 filesystems mounted for that cluster. The
|
|
Packit Service |
360c39 |
listOfGFS2Names is a list of GFS2 filesystem that need to have their data
|
|
Packit Service |
360c39 |
capture. If the list is empty then that means that all the mounted GFS2
|
|
Packit Service |
360c39 |
filesystems will be captured, if list is not empty then only those GFS2
|
|
Packit Service |
360c39 |
filesystems in the list will have their data captured.
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@return: Returns a cluster node object if there was mounted GFS2 filesystems
|
|
Packit Service |
360c39 |
found that will have their data captured.
|
|
Packit Service |
360c39 |
@rtype: ClusterNode
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@param listOfGFS2Names: A list of GFS2 filesystem names that will have their
|
|
Packit Service |
360c39 |
data captured. If the list is empty then that means that all the mounted
|
|
Packit Service |
360c39 |
GFS2 filesystems will be captured, if list is not empty then only those GFS2
|
|
Packit Service |
360c39 |
filesystems in the list will have their data captured.
|
|
Packit Service |
360c39 |
@type listOfGFS2Names: Array
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
# Return a ClusterNode object if the clusternode and cluster name are found
|
|
Packit Service |
360c39 |
# in the output, else return None.
|
|
Packit Service |
360c39 |
clusterName = ""
|
|
Packit Service |
360c39 |
clusternodeName = ""
|
|
Packit Service |
360c39 |
clusternodeID = ""
|
|
Packit Service |
360c39 |
if (runCommand("which", ["cman_tool"])):
|
|
Packit Service |
360c39 |
stdout = runCommandOutput("cman_tool", ["status"])
|
|
Packit Service |
360c39 |
if (not stdout == None):
|
|
Packit Service |
360c39 |
stdoutSplit = stdout.split("\n")
|
|
Packit Service |
360c39 |
clusterName = ""
|
|
Packit Service |
360c39 |
clusternodeName = ""
|
|
Packit Service |
360c39 |
for line in stdoutSplit:
|
|
Packit Service |
360c39 |
if (line.startswith("Cluster Name:")):
|
|
Packit Service |
360c39 |
clusterName = line.split("Cluster Name:")[1].strip().rstrip()
|
|
Packit Service |
360c39 |
if (line.startswith("Node name: ")):
|
|
Packit Service |
360c39 |
clusternodeName = line.split("Node name:")[1].strip().rstrip()
|
|
Packit Service |
360c39 |
if (line.startswith("Node ID: ")):
|
|
Packit Service |
360c39 |
clusternodeID = line.split("Node ID: ")[1].strip().rstrip()
|
|
Packit Service |
360c39 |
elif (runCommand("which", ["corosync-cmapctl"])):
|
|
Packit Service |
360c39 |
# Another way to get the local cluster node is: $ crm_node -i; crm_node -l
|
|
Packit Service |
360c39 |
# Get the name of the cluster.
|
|
Packit Service |
360c39 |
stdout = runCommandOutput("corosync-cmapctl", ["-g", "totem.cluster_name"])
|
|
Packit Service |
360c39 |
if (not stdout == None):
|
|
Packit Service |
360c39 |
stdoutSplit = stdout.split("=")
|
|
Packit Service |
360c39 |
if (len(stdoutSplit) == 2):
|
|
Packit Service |
360c39 |
clusterName = stdoutSplit[1].strip().rstrip()
|
|
Packit Service |
360c39 |
# Get the id of the local cluster node so we can get the clusternode name
|
|
Packit Service |
360c39 |
clusternodeID = ""
|
|
Packit Service |
360c39 |
stdout = runCommandOutput("corosync-cmapctl", ["-g", "runtime.votequorum.this_node_id"])
|
|
Packit Service |
360c39 |
if (not stdout == None):
|
|
Packit Service |
360c39 |
stdoutSplit = stdout.split("=")
|
|
Packit Service |
360c39 |
if (len(stdoutSplit) == 2):
|
|
Packit Service |
360c39 |
clusternodeID = stdoutSplit[1].strip().rstrip()
|
|
Packit Service |
360c39 |
# Now that we the nodeid then we can get the clusternode name.
|
|
Packit Service |
360c39 |
if (len(clusternodeID) > 0):
|
|
Packit Service |
360c39 |
stdout = runCommandOutput("corosync-quorumtool", ["-l"])
|
|
Packit Service |
360c39 |
if (not stdout == None):
|
|
Packit Service |
360c39 |
for line in stdout.split("\n"):
|
|
Packit Service |
360c39 |
if (line.find("local") >=0):
|
|
Packit Service |
360c39 |
splitLine = line.split(" (local)")
|
|
Packit Service |
360c39 |
clusternodeName = splitLine[0].split()[2]
|
|
Packit Service |
360c39 |
break;
|
|
Packit Service |
360c39 |
# If a clusternode name and cluster name was found then return a new object
|
|
Packit Service |
360c39 |
# since this means this cluster is part of cluster.
|
|
Packit Service |
360c39 |
if ((len(clusterName) > 0) and (len(clusternodeName) > 0)):
|
|
Packit Service |
360c39 |
mapOfMountedFilesystemLabels = getLabelMapForMountedFilesystems(clusterName, getMountedGFS2Filesystems())
|
|
Packit Service |
360c39 |
# These will be the GFS2 filesystems that will have their lockdump information gathered.
|
|
Packit Service |
360c39 |
if (len(listOfGFS2Names) > 0):
|
|
Packit Service |
360c39 |
for label in list(mapOfMountedFilesystemLabels.keys()):
|
|
Packit Service |
360c39 |
foundMatch = False
|
|
Packit Service |
360c39 |
for gfs2FSName in listOfGFS2Names:
|
|
Packit Service |
360c39 |
if ((gfs2FSName == label) or ("%s:%s"%(clusterName, gfs2FSName) == label)):
|
|
Packit Service |
360c39 |
foundMatch = True
|
|
Packit Service |
360c39 |
break
|
|
Packit Service |
360c39 |
if ((not foundMatch) and (label in mapOfMountedFilesystemLabels)):
|
|
Packit Service |
360c39 |
del(mapOfMountedFilesystemLabels[label])
|
|
Packit Service |
360c39 |
# Cast the node id to an int, and default is 0 if node is not found or
|
|
Packit Service |
360c39 |
# not castable.
|
|
Packit Service |
360c39 |
clusternodeIDInt = 0
|
|
Packit Service |
360c39 |
if (clusternodeID.isalnum()):
|
|
Packit Service |
360c39 |
try:
|
|
Packit Service |
360c39 |
clusternodeIDInt = int(clusternodeID)
|
|
Packit Service |
360c39 |
except(ValueError):
|
|
Packit Service |
360c39 |
pass
|
|
Packit Service |
360c39 |
return ClusterNode(clusternodeName, clusternodeIDInt, clusterName, mapOfMountedFilesystemLabels)
|
|
Packit Service |
360c39 |
else:
|
|
Packit Service |
360c39 |
return None
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
def parse_dlm_ls(dlm_ls):
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
This function returns the names of all the dlm lockspace names found with the
|
|
Packit Service |
360c39 |
commands "dlm_tool ls" or "group_tool ls" output.
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@return: A list of all the dlm lockspace names.
|
|
Packit Service |
360c39 |
@rtype: Array
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
dlmLockspaces = []
|
|
Packit Service |
360c39 |
if (not dlm_ls == None):
|
|
Packit Service |
360c39 |
dlm_ls = dlm_ls.replace("dlm lockspaces\n", "")
|
|
Packit Service |
360c39 |
dlmToolLSKeys = ["name", "id", "flags", "change", "members"]
|
|
Packit Service |
360c39 |
# Split on newlines
|
|
Packit Service |
360c39 |
dlm_lsSections = dlm_ls.split("\n\n")
|
|
Packit Service |
360c39 |
for section in dlm_lsSections:
|
|
Packit Service |
360c39 |
# Create tmp map to hold data
|
|
Packit Service |
360c39 |
if (section.startswith("fence domain")):
|
|
Packit Service |
360c39 |
# Not concerned with fence information.
|
|
Packit Service |
360c39 |
continue
|
|
Packit Service |
360c39 |
dlmToolLSMap = dict.fromkeys(dlmToolLSKeys)
|
|
Packit Service |
360c39 |
lines = section.split("\n")
|
|
Packit Service |
360c39 |
for line in lines:
|
|
Packit Service |
360c39 |
for dlmToolLSKey in list(dlmToolLSMap.keys()):
|
|
Packit Service |
360c39 |
if (line.startswith(dlmToolLSKey)):
|
|
Packit Service |
360c39 |
value = line.replace(dlmToolLSKey, " ", 1).strip().rstrip()
|
|
Packit Service |
360c39 |
dlmToolLSMap[dlmToolLSKey] = value
|
|
Packit Service |
360c39 |
if ((not dlmToolLSMap.get("name") == None) and (not dlmToolLSMap.get("id") == None)):
|
|
Packit Service |
360c39 |
dlmLockspaces.append(dlmToolLSMap.get("name"))
|
|
Packit Service |
360c39 |
return dlmLockspaces
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
def getGroupToolDLMLockspaces():
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
This function returns the names of all the dlm lockspace names found with the
|
|
Packit Service |
360c39 |
command: "group_tool ls".
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@return: A list of all the dlm lockspace names.
|
|
Packit Service |
360c39 |
@rtype: Array
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
dlmLockspaces = []
|
|
Packit Service |
360c39 |
stdout = runCommandOutput("group_tool", ["ls"])
|
|
Packit Service |
360c39 |
if (not stdout == None):
|
|
Packit Service |
360c39 |
lines = stdout.split("\n")
|
|
Packit Service |
360c39 |
if (len(lines) > 0):
|
|
Packit Service |
360c39 |
if (lines[0].startswith("type")):
|
|
Packit Service |
360c39 |
# Then running cman-2.0
|
|
Packit Service |
360c39 |
for line in lines:
|
|
Packit Service |
360c39 |
if (line.startswith("dlm")):
|
|
Packit Service |
360c39 |
dlmLockspaces.append(line.split()[2])
|
|
Packit Service |
360c39 |
else:
|
|
Packit Service |
360c39 |
# Then running cman-3.0 and uses same sorta output as `dlm_tool ls`.
|
|
Packit Service |
360c39 |
dlmLockspaces = parse_dlm_ls(stdout)
|
|
Packit Service |
360c39 |
return dlmLockspaces
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
def getDLMLockspaces():
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
Returns a list of the dlm lockspace names.
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@return: Returns a list of dlm lockspace names.
|
|
Packit Service |
360c39 |
@rtype: Array
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
message = "Gathering the DLM Lockspace Names."
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).debug(message)
|
|
Packit Service |
360c39 |
dlmLockspaces = parse_dlm_ls(runCommandOutput("dlm_tool", ["ls"]))
|
|
Packit Service |
360c39 |
if (not len(dlmLockspaces) > 0):
|
|
Packit Service |
360c39 |
message = "There was no dlm lockspaces found with the \"dlm_tool ls\" command. Trying with the \"group_tool ls\" command."
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).debug(message)
|
|
Packit Service |
360c39 |
dlmLockspaces = getGroupToolDLMLockspaces()
|
|
Packit Service |
360c39 |
return dlmLockspaces
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
def getVerifiedDLMLockspaceNames(lockspaceNames):
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
Returns a list of DLM lockspaces that have been verified to exists in the
|
|
Packit Service |
360c39 |
command output of $(dlm_tool ls).
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@return: Returns a list of DLM lockspaces that have been verified to exists
|
|
Packit Service |
360c39 |
in the command output of $(dlm_tool ls).
|
|
Packit Service |
360c39 |
@rtype: Array
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@param lockspaceNames: This is the list of DLM lockspaces that will have
|
|
Packit Service |
360c39 |
their debug directory copied.
|
|
Packit Service |
360c39 |
@type lockspaceNames: Array
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
# Get a list of all the DLM lockspaces names.
|
|
Packit Service |
360c39 |
dlmLockspaces = getDLMLockspaces()
|
|
Packit Service |
360c39 |
# Verify the lockspaceNames are lockspaces that exist.
|
|
Packit Service |
360c39 |
verifiedLockspaceNames = []
|
|
Packit Service |
360c39 |
for lockspaceName in lockspaceNames:
|
|
Packit Service |
360c39 |
if ((lockspaceName in dlmLockspaces) and
|
|
Packit Service |
360c39 |
(not lockspaceName in verifiedLockspaceNames)):
|
|
Packit Service |
360c39 |
verifiedLockspaceNames.append(lockspaceName)
|
|
Packit Service |
360c39 |
return verifiedLockspaceNames
|
|
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 |
stdout = runCommandOutput("mount", ["-l"])
|
|
Packit Service |
360c39 |
if (not stdout == None):
|
|
Packit Service |
360c39 |
stdoutSplit = stdout.split("\n")
|
|
Packit Service |
360c39 |
for line in stdoutSplit:
|
|
Packit Service |
360c39 |
splitLine = line.split()
|
|
Packit Service |
360c39 |
if (len(splitLine) >= 5):
|
|
Packit Service |
360c39 |
if (splitLine[4] == fsType):
|
|
Packit Service |
360c39 |
listOfMountedFilesystems.append(line)
|
|
Packit Service |
360c39 |
return listOfMountedFilesystems
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
def getLabelMapForMountedFilesystems(clusterName, listOfMountedFilesystems):
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
This function will return a dictionary of the mounted GFS2 filesystem that
|
|
Packit Service |
360c39 |
contain a label that starts with the cluster name. For example:
|
|
Packit Service |
360c39 |
{'f18cluster:mygfs2vol1': '/dev/vdb1 on /mnt/gfs2vol1 type gfs2 (rw,relatime) [f18cluster:mygfs2vol1]'}
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@return: Returns a dictionary of the mounted GFS2 filesystems that contain a
|
|
Packit Service |
360c39 |
label that starts with the cluster name.
|
|
Packit Service |
360c39 |
@rtype: Dict
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@param clusterName: The name of the cluster.
|
|
Packit Service |
360c39 |
@type clusterName: String
|
|
Packit Service |
360c39 |
@param listOfMountedFilesystems: A list of all the mounted GFS2 filesystems.
|
|
Packit Service |
360c39 |
@type listOfMountedFilesystems: Array
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
mapOfMountedFilesystemLabels = {}
|
|
Packit Service |
360c39 |
for mountedFilesystem in listOfMountedFilesystems:
|
|
Packit Service |
360c39 |
splitMountedFilesystem = mountedFilesystem.split()
|
|
Packit Service |
360c39 |
fsLabel = splitMountedFilesystem[-1].strip().strip("[").rstrip("]")
|
|
Packit Service |
360c39 |
if (len(fsLabel) > 0):
|
|
Packit Service |
360c39 |
# Verify it starts with name of the cluster.
|
|
Packit Service |
360c39 |
if (fsLabel.startswith("%s:" %(clusterName))):
|
|
Packit Service |
360c39 |
mapOfMountedFilesystemLabels[fsLabel] = mountedFilesystem
|
|
Packit Service |
360c39 |
return mapOfMountedFilesystemLabels
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
# #####################################################################
|
|
Packit Service |
360c39 |
# Gather output from command functions
|
|
Packit Service |
360c39 |
# #####################################################################
|
|
Packit Service |
360c39 |
def gatherHostData(pathToDSTDir):
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
This function will gather general information about the cluster and write
|
|
Packit Service |
360c39 |
the results to a file. The following data will be captured: hostname, date,
|
|
Packit Service |
360c39 |
uname -a, uptime.
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@param pathToDSTDir: This is the path to directory where the files will be
|
|
Packit Service |
360c39 |
written to.
|
|
Packit Service |
360c39 |
@type pathToDSTDir: String
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
# Gather some general information and write to system.txt.
|
|
Packit Service |
360c39 |
systemString = "HOSTNAME=%s\nTIMESTAMP=%s\n" %(platform.node(), time.strftime("%Y-%m-%d %H:%M:%S"))
|
|
Packit Service |
360c39 |
stdout = runCommandOutput("uname", ["-a"]).strip().rstrip()
|
|
Packit Service |
360c39 |
if (not stdout == None):
|
|
Packit Service |
360c39 |
systemString += "UNAMEA=%s\n" %(stdout)
|
|
Packit Service |
360c39 |
stdout = runCommandOutput("uptime", []).strip().rstrip()
|
|
Packit Service |
360c39 |
if (not stdout == None):
|
|
Packit Service |
360c39 |
systemString += "UPTIME=%s" %(stdout)
|
|
Packit Service |
360c39 |
writeToFile(os.path.join(pathToDSTDir, "hostinformation.txt"), systemString, createFile=True)
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
def gatherDiagnosticData(pathToDSTDir):
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
This function will gather general information about the cluster and write (or
|
|
Packit Service |
360c39 |
copy) the results to a file.
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@param pathToDSTDir: This is the path to directory where the files will be
|
|
Packit Service |
360c39 |
written to.
|
|
Packit Service |
360c39 |
@type pathToDSTDir: String
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
# Get "ps -eo user,pid,%cpu,%mem,vsz,rss,tty,stat,start,time,comm,wchan" data.
|
|
Packit Service |
360c39 |
# Get " ps h -AL -o tid,s,cmd
|
|
Packit Service |
360c39 |
command = "ps"
|
|
Packit Service |
360c39 |
pathToCommandOutput = os.path.join(pathToDSTDir, "ps_hALo-tid.s.cmd")
|
|
Packit Service |
360c39 |
try:
|
|
Packit Service |
360c39 |
fout = open(pathToCommandOutput, "w")
|
|
Packit Service |
360c39 |
#runCommand(command, ["-eo", "user,pid,%cpu,%mem,vsz,rss,tty,stat,start,time,comm,wchan"], standardOut=fout)
|
|
Packit Service |
360c39 |
runCommand(command, ["h", "-AL", "-o", "tid,s,cmd"], standardOut=fout)
|
|
Packit Service |
360c39 |
fout.close()
|
|
Packit Service |
360c39 |
except IOError:
|
|
Packit Service |
360c39 |
message = "There was an error writing the command output for %s to the file %s." %(command, pathToCommandOutput)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
# Copy misc files
|
|
Packit Service |
360c39 |
pathToSrcFile = "/proc/mounts"
|
|
Packit Service |
360c39 |
copyFile(pathToSrcFile, os.path.join(pathToDSTDir, pathToSrcFile.strip("/")))
|
|
Packit Service |
360c39 |
pathToSrcFile = "/proc/slabinfo"
|
|
Packit Service |
360c39 |
copyFile(pathToSrcFile, os.path.join(pathToDSTDir, pathToSrcFile.strip("/")))
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
# Copy the DLM hash table sizes:
|
|
Packit Service |
360c39 |
pathToHashTableFiles = ["/sys/kernel/config/dlm/cluster/lkbtbl_size", "/sys/kernel/config/dlm/cluster/dirtbl_size",
|
|
Packit Service |
360c39 |
"/sys/kernel/config/dlm/cluster/rsbtbl_size"]
|
|
Packit Service |
360c39 |
for pathToSrcFile in pathToHashTableFiles:
|
|
Packit Service |
360c39 |
if (os.path.exists(pathToSrcFile)):
|
|
Packit Service |
360c39 |
copyFile(pathToSrcFile, os.path.join(pathToDSTDir, pathToSrcFile.strip("/")))
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
def gatherOptionalDiagnosticData(pathToDSTDir):
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
This function will gather optional information about the cluster and write
|
|
Packit Service |
360c39 |
the results to a file.
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@param pathToDSTDir: This is the path to directory where the files will be
|
|
Packit Service |
360c39 |
written to.
|
|
Packit Service |
360c39 |
@type pathToDSTDir: String
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
# Get df -h ouput
|
|
Packit Service |
360c39 |
command = "df"
|
|
Packit Service |
360c39 |
pathToCommandOutput = os.path.join(pathToDSTDir, "df-h.cmd")
|
|
Packit Service |
360c39 |
try:
|
|
Packit Service |
360c39 |
fout = open(pathToCommandOutput, "w")
|
|
Packit Service |
360c39 |
runCommand(command, ["-h"], standardOut=fout)
|
|
Packit Service |
360c39 |
fout.close()
|
|
Packit Service |
360c39 |
except IOError:
|
|
Packit Service |
360c39 |
message = "There was an error writing the command output for %s to the file %s." %(command, pathToCommandOutput)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
# Write the status of all the nodes in the cluster out.
|
|
Packit Service |
360c39 |
if (runCommand("which", ["cman_tool"])):
|
|
Packit Service |
360c39 |
command = "cman_tool"
|
|
Packit Service |
360c39 |
pathToCommandOutput = os.path.join(pathToDSTDir, "cman_tool_status")
|
|
Packit Service |
360c39 |
try:
|
|
Packit Service |
360c39 |
fout = open(pathToCommandOutput, "w")
|
|
Packit Service |
360c39 |
runCommand(command, ["status"], standardOut=fout)
|
|
Packit Service |
360c39 |
fout.close()
|
|
Packit Service |
360c39 |
except IOError:
|
|
Packit Service |
360c39 |
message = "There was an error the command output for %s to the file %s." %(command, pathToCommandOutput)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
elif (runCommand("which", ["corosync-cmapctl"])):
|
|
Packit Service |
360c39 |
command = "corosync-quorumtool"
|
|
Packit Service |
360c39 |
pathToCommandOutput = os.path.join(pathToDSTDir, "corosync-quorumtool_l")
|
|
Packit Service |
360c39 |
try:
|
|
Packit Service |
360c39 |
fout = open(pathToCommandOutput, "w")
|
|
Packit Service |
360c39 |
runCommand(command, ["-l"], standardOut=fout)
|
|
Packit Service |
360c39 |
fout.close()
|
|
Packit Service |
360c39 |
except IOError:
|
|
Packit Service |
360c39 |
message = "There was an error the command output for %s to the file %s." %(command, pathToCommandOutput)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
# #####################################################################
|
|
Packit Service |
360c39 |
# Gather Process Information
|
|
Packit Service |
360c39 |
# #####################################################################
|
|
Packit Service |
360c39 |
def isProcPidStackEnabled(pathToPidData):
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
Returns true if the init process has the file "stack" in its pid data
|
|
Packit Service |
360c39 |
directory which contains the task functions for that process.
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@return: Returns true if the init process has the file "stack" in its pid
|
|
Packit Service |
360c39 |
data directory which contains the task functions for that process.
|
|
Packit Service |
360c39 |
@rtype: Boolean
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@param pathToPidData: The path to the directory where all the pid data
|
|
Packit Service |
360c39 |
directories are located.
|
|
Packit Service |
360c39 |
@type pathToPidData: String
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
return os.path.exists(os.path.join(pathToPidData, "1/stack"))
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
def gatherPidData(pathToPidData, pathToDSTDir):
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
This command will gather all the directories which contain data about all the pids.
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@return: Returns a list of paths to the directory that contains the
|
|
Packit Service |
360c39 |
information about the pid.
|
|
Packit Service |
360c39 |
@rtype: Array
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@param pathToPidData: The path to the directory where all the pid data
|
|
Packit Service |
360c39 |
directories are located.
|
|
Packit Service |
360c39 |
@type pathToPidData: String
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
# Status has: command name, pid, ppid, state, possibly registers
|
|
Packit Service |
360c39 |
listOfFilesToCopy = ["cmdline", "stack", "status"]
|
|
Packit Service |
360c39 |
listOfPathToPidsData = []
|
|
Packit Service |
360c39 |
if (os.path.exists(pathToPidData)):
|
|
Packit Service |
360c39 |
for srcFilename in os.listdir(pathToPidData):
|
|
Packit Service |
360c39 |
pathToPidDirDST = os.path.join(pathToDSTDir, srcFilename)
|
|
Packit Service |
360c39 |
if (srcFilename.isdigit()):
|
|
Packit Service |
360c39 |
pathToSrcDir = os.path.join(pathToPidData, srcFilename)
|
|
Packit Service |
360c39 |
for filenameToCopy in listOfFilesToCopy:
|
|
Packit Service |
360c39 |
copyFile(os.path.join(pathToSrcDir, filenameToCopy), os.path.join(pathToPidDirDST, filenameToCopy))
|
|
Packit Service |
360c39 |
if (os.path.exists(pathToPidDirDST)):
|
|
Packit Service |
360c39 |
listOfPathToPidsData.append(pathToPidDirDST)
|
|
Packit Service |
360c39 |
return listOfPathToPidsData
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
def triggerSysRQEvents():
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
This command will trigger sysrq events which will write the output to
|
|
Packit Service |
360c39 |
/var/log/messages. The events that will be trigger are "m" and "t". The "m"
|
|
Packit Service |
360c39 |
event will dump information about memory allocation. The "t" event will dump
|
|
Packit Service |
360c39 |
all the threads state information.
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
command = "echo"
|
|
Packit Service |
360c39 |
pathToSysrqTriggerFile = "/proc/sysrq-trigger"
|
|
Packit Service |
360c39 |
# m - dump information about memory allocation
|
|
Packit Service |
360c39 |
# t - dump thread state information
|
|
Packit Service |
360c39 |
# triggers = ["m", "t"]
|
|
Packit Service |
360c39 |
triggers = ["t"]
|
|
Packit Service |
360c39 |
for trigger in triggers:
|
|
Packit Service |
360c39 |
try:
|
|
Packit Service |
360c39 |
fout = open(pathToSysrqTriggerFile, "w")
|
|
Packit Service |
360c39 |
runCommand(command, [trigger], standardOut=fout)
|
|
Packit Service |
360c39 |
fout.close()
|
|
Packit Service |
360c39 |
except IOError:
|
|
Packit Service |
360c39 |
message = "There was an error writing the command output for %s to the file %s." %(command, pathToSysrqTriggerFile)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
# #####################################################################
|
|
Packit Service |
360c39 |
# Gather lockdumps and logs
|
|
Packit Service |
360c39 |
# #####################################################################
|
|
Packit Service |
360c39 |
def gatherLogs(pathToDSTDir):
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
This function will copy all the cluster logs(/var/log/cluster) and the
|
|
Packit Service |
360c39 |
system log(/var/log/messages) to the directory given by pathToDSTDir.
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@param pathToDSTDir: This is the path to directory where the files will be
|
|
Packit Service |
360c39 |
copied to.
|
|
Packit Service |
360c39 |
@type pathToDSTDir: String
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
pathToLogFile = "/var/log/messages"
|
|
Packit Service |
360c39 |
pathToDSTLogFile = os.path.join(pathToDSTDir, os.path.basename(pathToLogFile))
|
|
Packit Service |
360c39 |
copyFile(pathToLogFile, pathToDSTLogFile)
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
pathToLogDir = "/var/log/cluster"
|
|
Packit Service |
360c39 |
if (os.path.exists(pathToLogDir)):
|
|
Packit Service |
360c39 |
pathToDSTLogDir = os.path.join(pathToDSTDir, os.path.basename(pathToLogDir))
|
|
Packit Service |
360c39 |
copyDirectory(pathToLogDir, pathToDSTDir)
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
def gatherDLMLockDumps(pathToDSTDir, lockspaceNames):
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
This function copies all the debug files for dlm and sorts them into their
|
|
Packit Service |
360c39 |
own directory based on name of dlm lockspace.
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@param pathToDSTDir: This is the path to directory where the files will be
|
|
Packit Service |
360c39 |
copied to.
|
|
Packit Service |
360c39 |
@type pathToDSTDir: String
|
|
Packit Service |
360c39 |
@param lockspaceNames: This is the list of DLM lockspaces that will have
|
|
Packit Service |
360c39 |
their debug directory copied.
|
|
Packit Service |
360c39 |
@type lockspaceNames: Array
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
# This function assumes that verifiedLockspaceNames has already been called
|
|
Packit Service |
360c39 |
# to verify the lockspace does exist.
|
|
Packit Service |
360c39 |
lockDumpType = "dlm"
|
|
Packit Service |
360c39 |
pathToSrcDir = os.path.join(PATH_TO_DEBUG_DIR, lockDumpType)
|
|
Packit Service |
360c39 |
pathToOutputDir = os.path.join(pathToDSTDir, lockDumpType)
|
|
Packit Service |
360c39 |
message = "Copying the files in the %s lockdump data directory %s." %(lockDumpType.upper(), pathToSrcDir)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).debug(message)
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
# Get list of all the dlm lockspaces
|
|
Packit Service |
360c39 |
if (os.path.exists(pathToSrcDir)):
|
|
Packit Service |
360c39 |
for filename in os.listdir(pathToSrcDir):
|
|
Packit Service |
360c39 |
for lockspaceName in lockspaceNames:
|
|
Packit Service |
360c39 |
if (filename.startswith(lockspaceName)):
|
|
Packit Service |
360c39 |
copyFile(os.path.join(pathToSrcDir, filename),
|
|
Packit Service |
360c39 |
os.path.join(os.path.join(pathToOutputDir, lockspaceName), filename))
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
# Run dlm_tool lockdebug against the lockspace names and write to file.
|
|
Packit Service |
360c39 |
for lockspaceName in lockspaceNames:
|
|
Packit Service |
360c39 |
dstDir = os.path.join(pathToOutputDir, lockspaceName)
|
|
Packit Service |
360c39 |
if (mkdirs(dstDir)):
|
|
Packit Service |
360c39 |
pathToCommandOutput = os.path.join(dstDir,"%s_lockdebug" %(lockspaceName))
|
|
Packit Service |
360c39 |
try:
|
|
Packit Service |
360c39 |
fout = open(pathToCommandOutput, "w")
|
|
Packit Service |
360c39 |
runCommand("dlm_tool", ["lockdebug", "-v", "-s", "-w", lockspaceName], standardOut=fout)
|
|
Packit Service |
360c39 |
fout.close()
|
|
Packit Service |
360c39 |
except IOError:
|
|
Packit Service |
360c39 |
message = "There was an error writing the command output to the file %s." %(pathToCommandOutput)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
def gatherGFS2LockDumps(pathToDSTDir, listOfGFS2Filesystems):
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
This function copies the debug directory for a GFS2 filesystems in the list
|
|
Packit Service |
360c39 |
to a directory. The list of GFS2 filesystems will include the cluster name
|
|
Packit Service |
360c39 |
and filesystem name for each item in the list. For example:
|
|
Packit Service |
360c39 |
"f18cluster:mygfs2vol1"
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@return: Returns True if files(not directories) were copied to the
|
|
Packit Service |
360c39 |
destination directory.
|
|
Packit Service |
360c39 |
@rtype: Boolean
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
@param pathToDSTDir: This is the path to directory where the files will be
|
|
Packit Service |
360c39 |
copied to.
|
|
Packit Service |
360c39 |
@type pathToDSTDir: String
|
|
Packit Service |
360c39 |
@param listOfGFS2Filesystems: This is the list of the GFS2 filesystems that
|
|
Packit Service |
360c39 |
will have their debug directory copied.
|
|
Packit Service |
360c39 |
@type listOfGFS2Filesystems: Array
|
|
Packit Service |
360c39 |
"""
|
|
Packit Service |
360c39 |
lockDumpType = "gfs2"
|
|
Packit Service |
360c39 |
pathToSrcDir = os.path.join(PATH_TO_DEBUG_DIR, lockDumpType)
|
|
Packit Service |
360c39 |
pathToOutputDir = os.path.join(pathToDSTDir, lockDumpType)
|
|
Packit Service |
360c39 |
# The number of files that were copied
|
|
Packit Service |
360c39 |
fileCopiedCount = 0
|
|
Packit Service |
360c39 |
if (not os.path.exists(pathToSrcDir)):
|
|
Packit Service |
360c39 |
return False
|
|
Packit Service |
360c39 |
for dirName in os.listdir(pathToSrcDir):
|
|
Packit Service |
360c39 |
pathToCurrentDir = os.path.join(pathToSrcDir, dirName)
|
|
Packit Service |
360c39 |
if ((os.path.isdir(pathToCurrentDir)) and (dirName in listOfGFS2Filesystems)):
|
|
Packit Service |
360c39 |
message = "Copying the lockdump data for the %s filesystem: %s" %(lockDumpType.upper(), dirName)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).debug(message)
|
|
Packit Service |
360c39 |
copySuccessful = copyDirectory(pathToCurrentDir, pathToOutputDir)
|
|
Packit Service |
360c39 |
if (copySuccessful and os.path.exists(os.path.join(pathToOutputDir, dirName))):
|
|
Packit Service |
360c39 |
fileCopiedCount = len(os.listdir(os.path.join(pathToOutputDir, dirName)))
|
|
Packit Service |
360c39 |
# If the number of files(not directories) copied was greater than zero then files were copied
|
|
Packit Service |
360c39 |
# succesfully.
|
|
Packit Service |
360c39 |
return (fileCopiedCount > 0)
|
|
Packit Service |
360c39 |
|
|
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("-y", "--no_ask",
|
|
Packit Service |
360c39 |
action="store_true",
|
|
Packit Service |
360c39 |
dest="disableQuestions",
|
|
Packit Service |
360c39 |
help="disables all questions and assumes yes",
|
|
Packit Service |
360c39 |
default=False)
|
|
Packit Service |
360c39 |
cmdParser.add_option("-i", "--info",
|
|
Packit Service |
360c39 |
action="store_true",
|
|
Packit Service |
360c39 |
dest="enablePrintInfo",
|
|
Packit Service |
360c39 |
help="prints information about the mounted GFS2 file-systems",
|
|
Packit Service |
360c39 |
default=False)
|
|
Packit Service |
360c39 |
cmdParser.add_option("-P", "--disable_process_gather",
|
|
Packit Service |
360c39 |
action="store_true",
|
|
Packit Service |
360c39 |
dest="disableProcessGather",
|
|
Packit Service |
360c39 |
help="the gathering of process information will be disabled",
|
|
Packit Service |
360c39 |
default=False)
|
|
Packit Service |
360c39 |
cmdParser.add_option("-m", "--diagnostic_data",
|
|
Packit Service |
360c39 |
action="store_true",
|
|
Packit Service |
360c39 |
dest="enableDiagnosticData",
|
|
Packit Service |
360c39 |
help=SUPPRESS_HELP,
|
|
Packit Service |
360c39 |
default=False)
|
|
Packit Service |
360c39 |
cmdParser.add_option("-o", "--path_to_output_dir",
|
|
Packit Service |
360c39 |
action="store",
|
|
Packit Service |
360c39 |
dest="pathToOutputDir",
|
|
Packit Service |
360c39 |
help="the directory where all the collect data will be stored",
|
|
Packit Service |
360c39 |
type="string",
|
|
Packit Service |
360c39 |
metavar="<output directory>",
|
|
Packit Service |
360c39 |
default="/tmp")
|
|
Packit Service |
360c39 |
cmdParser.add_option("-r", "--num_of_runs",
|
|
Packit Service |
360c39 |
action="store",
|
|
Packit Service |
360c39 |
dest="numberOfRuns",
|
|
Packit Service |
360c39 |
help="number of runs capturing the lockdump data(default: 3 runs)",
|
|
Packit Service |
360c39 |
type="int",
|
|
Packit Service |
360c39 |
metavar="<number of runs>",
|
|
Packit Service |
360c39 |
default=3)
|
|
Packit Service |
360c39 |
cmdParser.add_option("-s", "--seconds_sleep",
|
|
Packit Service |
360c39 |
action="store",
|
|
Packit Service |
360c39 |
dest="secondsToSleep",
|
|
Packit Service |
360c39 |
help="number of seconds to sleep between runs of capturing the lockdump data(default: 120 seconds)",
|
|
Packit Service |
360c39 |
type="int",
|
|
Packit Service |
360c39 |
metavar="<seconds to sleep>",
|
|
Packit Service |
360c39 |
default=120)
|
|
Packit Service |
360c39 |
cmdParser.add_option("-n", "--fs_name",
|
|
Packit Service |
360c39 |
action="extend",
|
|
Packit Service |
360c39 |
dest="listOfGFS2Names",
|
|
Packit Service |
360c39 |
help="name of the GFS2 filesystem(s) that will have their lockdump data captured(default: all GFS2 file-systems will be captured)",
|
|
Packit Service |
360c39 |
type="string",
|
|
Packit Service |
360c39 |
metavar="<name of GFS2 filesystem>",
|
|
Packit Service |
360c39 |
default=[])
|
|
Packit Service |
360c39 |
# Get the options and return the result.
|
|
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 gfs2_lockcapture will capture locking information from GFS2 file systems and DLM.\n"%(self.__commandName)
|
|
Packit Service |
360c39 |
|
|
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 |
self.print_version()
|
|
Packit Service |
360c39 |
examplesMessage = "\n"
|
|
Packit Service |
360c39 |
examplesMessage = "\nPrints information about the available GFS2 filesystems that can have lockdump data captured."
|
|
Packit Service |
360c39 |
examplesMessage += "\n# %s -i\n" %(self.__commandName)
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
examplesMessage += "\nIt will do 3 runs of gathering the lockdump information in 10 second intervals for only the"
|
|
Packit Service |
360c39 |
examplesMessage += "\nGFS2 filesystems with the names myGFS2vol2,myGFS2vol1. Then it will archive and compress"
|
|
Packit Service |
360c39 |
examplesMessage += "\nthe data collected in the output directory /tmp and all the questions will be answered with yes.\n"
|
|
Packit Service |
360c39 |
examplesMessage += "\n# %s -r 3 -s 10 -n myGFS2vol2,myGFS2vol1 -o /tmp -y\n" %(self.__commandName)
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
examplesMessage += "\nIt will do 2 runs of gathering the lockdump information in 25 second intervals for all the"
|
|
Packit Service |
360c39 |
examplesMessage += "\nmounted GFS2 filesystems. The gathering process data will be disabled. Then it will archive and compress"
|
|
Packit Service |
360c39 |
examplesMessage += "\nthe data collected in the output directory: /tmp and all the questions will be answered with yes.\n"
|
|
Packit Service |
360c39 |
examplesMessage += "\n# %s -r 2 -s 25 -P -o /tmp\n" %(self.__commandName)
|
|
Packit Service |
360c39 |
OptionParser.print_help(self)
|
|
Packit Service |
360c39 |
print(examplesMessage)
|
|
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 |
newValue = value.strip().rstrip()
|
|
Packit Service |
360c39 |
if (len(newValue) > 0):
|
|
Packit Service |
360c39 |
valueList.append(newValue)
|
|
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 |
"""
|
|
Packit Service |
360c39 |
When the script is executed then this code is ran. If there was files(not
|
|
Packit Service |
360c39 |
directories) created then 0 will be returned, else a 1 is returned.
|
|
Packit Service |
360c39 |
"""
|
|
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 |
# Setup the logger and create config directory
|
|
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 |
|
|
Packit Service |
360c39 |
# Log to main system logger that script has started then close the
|
|
Packit Service |
360c39 |
# handler before the other handlers are created.
|
|
Packit Service |
360c39 |
sysLogHandler = logging.handlers.SysLogHandler(address = '/dev/log')
|
|
Packit Service |
360c39 |
logger.addHandler(sysLogHandler)
|
|
Packit Service |
360c39 |
logger.info("Capturing of the data to analyze GFS2 lockdumps.")
|
|
Packit Service |
360c39 |
logger.removeHandler(sysLogHandler)
|
|
Packit Service |
360c39 |
|
|
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.setLevel(logLevel)
|
|
Packit Service |
360c39 |
streamHandler.setFormatter(logging.Formatter("%(levelname)s %(message)s"))
|
|
Packit Service |
360c39 |
logger.addHandler(streamHandler)
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
# Please note there will not be a global log file created. If a log file
|
|
Packit Service |
360c39 |
# is needed then redirect the output. There will be a log file created
|
|
Packit Service |
360c39 |
# for each run in the corresponding directory.
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
# #######################################################################
|
|
Packit Service |
360c39 |
# Set the logging levels.
|
|
Packit Service |
360c39 |
# #######################################################################
|
|
Packit Service |
360c39 |
if ((cmdLineOpts.enableDebugLogging) and (not cmdLineOpts.disableLoggingToConsole)):
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).setLevel(logging.DEBUG)
|
|
Packit Service |
360c39 |
streamHandler.setLevel(logging.DEBUG)
|
|
Packit Service |
360c39 |
message = "Debugging has been enabled."
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).debug(message)
|
|
Packit Service |
360c39 |
if (cmdLineOpts.disableLoggingToConsole):
|
|
Packit Service |
360c39 |
streamHandler.setLevel(logging.CRITICAL)
|
|
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 |
writeToFile(PATH_TO_PID_FILENAME, str(os.getpid()), createFile=True)
|
|
Packit Service |
360c39 |
# #######################################################################
|
|
Packit Service |
360c39 |
# Get the clusternode name and verify that mounted GFS2 filesystems were
|
|
Packit Service |
360c39 |
# found.
|
|
Packit Service |
360c39 |
# #######################################################################
|
|
Packit Service |
360c39 |
clusternode = getClusterNode(cmdLineOpts.listOfGFS2Names)
|
|
Packit Service |
360c39 |
if (clusternode == None):
|
|
Packit Service |
360c39 |
message = "The cluster or cluster node name could not be found."
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
exitScript(removePidFile=True, errorCode=1)
|
|
Packit Service |
360c39 |
elif (not len(clusternode.getMountedGFS2FilesystemNames()) > 0):
|
|
Packit Service |
360c39 |
message = "There were no mounted GFS2 filesystems found."
|
|
Packit Service |
360c39 |
if (len(cmdLineOpts.listOfGFS2Names) > 0):
|
|
Packit Service |
360c39 |
message = "There were no mounted GFS2 filesystems found with the name:"
|
|
Packit Service |
360c39 |
for name in cmdLineOpts.listOfGFS2Names:
|
|
Packit Service |
360c39 |
message += " %s" %(name)
|
|
Packit Service |
360c39 |
message += "."
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
if (cmdLineOpts.enablePrintInfo):
|
|
Packit Service |
360c39 |
logging.disable(logging.CRITICAL)
|
|
Packit Service |
360c39 |
print("List of all the mounted GFS2 filesystems that can have their lockdump data captured:")
|
|
Packit Service |
360c39 |
print(clusternode)
|
|
Packit Service |
360c39 |
exitScript()
|
|
Packit Service |
360c39 |
# #######################################################################
|
|
Packit Service |
360c39 |
# Verify they want to continue because this script will trigger sysrq events.
|
|
Packit Service |
360c39 |
# #######################################################################
|
|
Packit Service |
360c39 |
if (not cmdLineOpts.disableQuestions and not cmdLineOpts.disableProcessGather):
|
|
Packit Service |
360c39 |
valid = {"yes":True, "y":True, "no":False, "n":False}
|
|
Packit Service |
360c39 |
question = "This script will trigger a sysrq -t event or collect the data for each pid directory located in /proc for each run. Are you sure you want to continue?"
|
|
Packit Service |
360c39 |
prompt = " [y/n] "
|
|
Packit Service |
360c39 |
while True:
|
|
Packit Service |
360c39 |
sys.stdout.write(question + prompt)
|
|
Packit Service |
360c39 |
try: # python2 compatible input
|
|
Packit Service |
360c39 |
input = raw_input
|
|
Packit Service |
360c39 |
except NameError:
|
|
Packit Service |
360c39 |
pass
|
|
Packit Service |
360c39 |
choice = input().lower()
|
|
Packit Service |
360c39 |
if (choice in valid):
|
|
Packit Service |
360c39 |
if (valid.get(choice)):
|
|
Packit Service |
360c39 |
# If yes, or y then exit loop and continue.
|
|
Packit Service |
360c39 |
break
|
|
Packit Service |
360c39 |
else:
|
|
Packit Service |
360c39 |
message = "The script will not continue since you chose not to continue."
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
exitScript(removePidFile=True, errorCode=1)
|
|
Packit Service |
360c39 |
else:
|
|
Packit Service |
360c39 |
sys.stdout.write("Please respond with '(y)es' or '(n)o'.\n")
|
|
Packit Service |
360c39 |
# #######################################################################
|
|
Packit Service |
360c39 |
# Create the output directory to verify it can be created before
|
|
Packit Service |
360c39 |
# proceeding unless it is already created from a previous run data needs
|
|
Packit Service |
360c39 |
# to be analyzed. Probably could add more debugging on if file or dir.
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
# Backup any existing directory with same name as current output
|
|
Packit Service |
360c39 |
# directory.
|
|
Packit Service |
360c39 |
# #######################################################################
|
|
Packit Service |
360c39 |
pathToOutputDir = "%s" %(os.path.join(cmdLineOpts.pathToOutputDir, "%s-%s" %(os.path.basename(sys.argv[0]), time.strftime("%Y-%m-%d"))))
|
|
Packit Service |
360c39 |
if (backupOutputDirectory(pathToOutputDir)):
|
|
Packit Service |
360c39 |
message = "This directory that will be used to capture all the data: %s" %(pathToOutputDir)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).info(message)
|
|
Packit Service |
360c39 |
if (not mkdirs(pathToOutputDir)):
|
|
Packit Service |
360c39 |
exitScript(errorCode=1)
|
|
Packit Service |
360c39 |
else:
|
|
Packit Service |
360c39 |
# There was an existing directory with same path as current output
|
|
Packit Service |
360c39 |
# directory and it failed to back it up.
|
|
Packit Service |
360c39 |
message = "Please change the output directory path (-o) or manual rename or remove the existing path: %s" %(pathToOutputDir)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).info(message)
|
|
Packit Service |
360c39 |
exitScript(errorCode=1)
|
|
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).info(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 |
# Gather data and the lockdumps.
|
|
Packit Service |
360c39 |
# #######################################################################
|
|
Packit Service |
360c39 |
if (cmdLineOpts.numberOfRuns <= 0):
|
|
Packit Service |
360c39 |
message = "The number of runs must be greater than zero."
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).warning(message)
|
|
Packit Service |
360c39 |
exitScript(errorCode=1)
|
|
Packit Service |
360c39 |
# If GFS2 lockdump files were successfully copied to output directory
|
|
Packit Service |
360c39 |
# then the exit code will be set to 0, else the exit code will be 1.
|
|
Packit Service |
360c39 |
exitCode = 1
|
|
Packit Service |
360c39 |
for i in range(1,(cmdLineOpts.numberOfRuns + 1)):
|
|
Packit Service |
360c39 |
# The current log count that will start at 1 and not zero to make it
|
|
Packit Service |
360c39 |
# make sense in logs.
|
|
Packit Service |
360c39 |
# Add clusternode name under each run dir to make combining multple
|
|
Packit Service |
360c39 |
# clusternode gfs2_lockgather data together and all data in each run directory.
|
|
Packit Service |
360c39 |
pathToOutputRunDir = os.path.join(pathToOutputDir, "run%d/%s" %(i, clusternode.getClusterNodeName()))
|
|
Packit Service |
360c39 |
# Create the the directory that will be used to capture the data.
|
|
Packit Service |
360c39 |
if (not mkdirs(pathToOutputRunDir)):
|
|
Packit Service |
360c39 |
exitScript(errorCode=1)
|
|
Packit Service |
360c39 |
# Set the handler for writing to log file for this run.
|
|
Packit Service |
360c39 |
currentRunFileHandler = None
|
|
Packit Service |
360c39 |
pathToLogFile = os.path.join(pathToOutputRunDir, "%s.log" %(MAIN_LOGGER_NAME))
|
|
Packit Service |
360c39 |
if (((os.access(pathToLogFile, os.W_OK) and os.access("/tmp", os.R_OK))) or (not os.path.exists(pathToLogFile))):
|
|
Packit Service |
360c39 |
currentRunFileHandler = logging.FileHandler(pathToLogFile)
|
|
Packit Service |
360c39 |
currentRunFileHandler.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(message)s", "%Y-%m-%d %H:%M:%S"))
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).addHandler(currentRunFileHandler)
|
|
Packit Service |
360c39 |
message = "Pass (%d/%d): Gathering all the lockdump data." %(i, cmdLineOpts.numberOfRuns)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).status(message)
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
# Gather various bits of data from the clusternode.
|
|
Packit Service |
360c39 |
message = "Pass (%d/%d): Gathering simple data about the host." %(i, cmdLineOpts.numberOfRuns)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).debug(message)
|
|
Packit Service |
360c39 |
gatherHostData(pathToOutputRunDir)
|
|
Packit Service |
360c39 |
# Write the clusternode name and id to the general information file.
|
|
Packit Service |
360c39 |
writeToFile(os.path.join(pathToOutputRunDir, "hostinformation.txt"),
|
|
Packit Service |
360c39 |
"NODE_NAME=%s\nNODE_ID=%d" %(clusternode.getClusterNodeName(), clusternode.getClusterNodeID()),
|
|
Packit Service |
360c39 |
appendToFile=True, createFile=True)
|
|
Packit Service |
360c39 |
# #######################################################################
|
|
Packit Service |
360c39 |
# Gather the DLM data and lock-dumps
|
|
Packit Service |
360c39 |
# #######################################################################
|
|
Packit Service |
360c39 |
# Gather data for the DLM lockspaces that are found.
|
|
Packit Service |
360c39 |
lockspaceNames = clusternode.getMountedGFS2FilesystemNames(includeClusterName=False)
|
|
Packit Service |
360c39 |
# In addition always gather these lockspaces(if they exist).
|
|
Packit Service |
360c39 |
lockspaceNames.append("clvmd")
|
|
Packit Service |
360c39 |
lockspaceNames.append("rgmanager")
|
|
Packit Service |
360c39 |
# Verify that these lockspace names exist.
|
|
Packit Service |
360c39 |
lockspaceNames = getVerifiedDLMLockspaceNames(lockspaceNames)
|
|
Packit Service |
360c39 |
# Gather the dlm locks.
|
|
Packit Service |
360c39 |
message = "Pass (%d/%d): Gathering the DLM lock-dumps for the host." %(i, cmdLineOpts.numberOfRuns)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).debug(message)
|
|
Packit Service |
360c39 |
# Add other notable lockspace names that should be captured if they exist.
|
|
Packit Service |
360c39 |
gatherDLMLockDumps(pathToOutputRunDir, lockspaceNames)
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
# #######################################################################
|
|
Packit Service |
360c39 |
# Gather the GFS2 data and lock-dumps
|
|
Packit Service |
360c39 |
# #######################################################################
|
|
Packit Service |
360c39 |
# Gather the glock locks from gfs2.
|
|
Packit Service |
360c39 |
message = "Pass (%d/%d): Gathering the GFS2 lock-dumps for the host." %(i, cmdLineOpts.numberOfRuns)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).debug(message)
|
|
Packit Service |
360c39 |
if(gatherGFS2LockDumps(pathToOutputRunDir, clusternode.getMountedGFS2FilesystemNames())):
|
|
Packit Service |
360c39 |
exitCode = 0
|
|
Packit Service |
360c39 |
# If enabled then gather the process data. This will be included even if -R option is enabled.
|
|
Packit Service |
360c39 |
if (not cmdLineOpts.disableProcessGather):
|
|
Packit Service |
360c39 |
# Gather the backtraces for all the pids, by grabbing the /proc/
|
|
Packit Service |
360c39 |
# number> or triggering sysrq events to capture task bask traces
|
|
Packit Service |
360c39 |
# from log.
|
|
Packit Service |
360c39 |
# Gather the data in the /proc/<pid> directory if the file
|
|
Packit Service |
360c39 |
# </proc/<pid>/stack exists. If file exists we will not trigger
|
|
Packit Service |
360c39 |
# sysrq events.
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
# Should I gather anyhow and only capture sysrq if needed.
|
|
Packit Service |
360c39 |
pathToPidData = "/proc"
|
|
Packit Service |
360c39 |
if (isProcPidStackEnabled(pathToPidData)):
|
|
Packit Service |
360c39 |
message = "Pass (%d/%d): Triggering the capture of all pid directories in %s." %(i, cmdLineOpts.numberOfRuns, pathToPidData)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).debug(message)
|
|
Packit Service |
360c39 |
gatherPidData(pathToPidData, os.path.join(pathToOutputRunDir, pathToPidData.strip("/")))
|
|
Packit Service |
360c39 |
else:
|
|
Packit Service |
360c39 |
message = "Pass (%d/%d): Triggering the sysrq events for the host since stack was not captured in pid directory." %(i, cmdLineOpts.numberOfRuns)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).debug(message)
|
|
Packit Service |
360c39 |
triggerSysRQEvents()
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
# Gather log files
|
|
Packit Service |
360c39 |
message = "Pass (%d/%d): Gathering the log files for the host." %(i, cmdLineOpts.numberOfRuns)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).debug(message)
|
|
Packit Service |
360c39 |
gatherLogs(os.path.join(pathToOutputRunDir, "logs"))
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
# Gather diagnostic data
|
|
Packit Service |
360c39 |
message = "Pass (%d/%d): Gathering diagnostic data about the host." %(i, cmdLineOpts.numberOfRuns)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).debug(message)
|
|
Packit Service |
360c39 |
gatherDiagnosticData(pathToOutputRunDir)
|
|
Packit Service |
360c39 |
if (cmdLineOpts.enableDiagnosticData):
|
|
Packit Service |
360c39 |
# Gather diagnostic data
|
|
Packit Service |
360c39 |
message = "Pass (%d/%d): Gathering optional diagnostic data about the host." %(i, cmdLineOpts.numberOfRuns)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).debug(message)
|
|
Packit Service |
360c39 |
gatherOptionalDiagnosticData(pathToOutputRunDir)
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
# #######################################################################
|
|
Packit Service |
360c39 |
# Sleep for X seconds between runs
|
|
Packit Service |
360c39 |
# #######################################################################
|
|
Packit Service |
360c39 |
# Sleep between each run if secondsToSleep is greater than or equal
|
|
Packit Service |
360c39 |
# to 0 and current run is not the last run. Add 2 seconds to each sleep so
|
|
Packit Service |
360c39 |
# that we know that there is a timestamp difference in logs between runs.
|
|
Packit Service |
360c39 |
# The minimal sleep is 2 seconds.
|
|
Packit Service |
360c39 |
secondsToSleep = cmdLineOpts.secondsToSleep + 2
|
|
Packit Service |
360c39 |
if (secondsToSleep < 2):
|
|
Packit Service |
360c39 |
secondsToSleep = 2
|
|
Packit Service |
360c39 |
if (i < cmdLineOpts.numberOfRuns):
|
|
Packit Service |
360c39 |
message = "The script will sleep for %d seconds between each run of capturing the lockdump data." %(secondsToSleep)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).info(message)
|
|
Packit Service |
360c39 |
time.sleep(secondsToSleep)
|
|
Packit Service |
360c39 |
# Remove the handler:
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).removeHandler(currentRunFileHandler)
|
|
Packit Service |
360c39 |
|
|
Packit Service |
360c39 |
# #######################################################################
|
|
Packit Service |
360c39 |
# Archive the directory that contains all the data and archive it after
|
|
Packit Service |
360c39 |
# all the information has been gathered.
|
|
Packit Service |
360c39 |
# #######################################################################
|
|
Packit Service |
360c39 |
message = "All the files have been gathered and this directory contains all the captured data: %s" %(pathToOutputDir)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).info(message)
|
|
Packit Service |
360c39 |
message = "The lockdump data will now be archive. This could some time depending on the size of the data collected."
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).info(message)
|
|
Packit Service |
360c39 |
pathToTarFilename = archiveData(pathToOutputDir)
|
|
Packit Service |
360c39 |
if (os.path.exists(pathToTarFilename)):
|
|
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 |
# Do some cleanup by removing the directory of the data if file archived file was created.
|
|
Packit Service |
360c39 |
try:
|
|
Packit Service |
360c39 |
shutil.rmtree(pathToOutputDir)
|
|
Packit Service |
360c39 |
except OSError:
|
|
Packit Service |
360c39 |
message = "There was an error removing the directory: %s." %(pathToOutputDir)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
else:
|
|
Packit Service |
360c39 |
message = "The compressed archvied failed to be created: %s" %(pathToTarFilename)
|
|
Packit Service |
360c39 |
logging.getLogger(MAIN_LOGGER_NAME).error(message)
|
|
Packit Service |
360c39 |
# #######################################################################
|
|
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(errorCode=1)
|
|
Packit Service |
360c39 |
# #######################################################################
|
|
Packit Service |
360c39 |
# Exit the application with zero exit code since we cleanly exited.
|
|
Packit Service |
360c39 |
# #######################################################################
|
|
Packit Service |
360c39 |
exitScript(errorCode=exitCode)
|