# This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import cPickle import commands import os import re import sys import logging import cas.cas_shutil as shutil from cas.cas_subprocess import Popen, PIPE, call class Logging(object): def __init__(self, dst, logger_id, debug_level='DEBUG'): self.debug_level = debug_level self.dst = dst self.logger_id = logger_id self.logfile = logger_id+".log" self.logfile = os.path.join(self.dst, self.logfile) self.log = logging.getLogger(self.logger_id) ch = logging.StreamHandler() # never fail if directory doesn't exist. if not os.path.exists(os.path.dirname(self.logfile)): os.makedirs(os.path.dirname(self.logfile)) fh = logging.FileHandler(self.logfile) self.log.addHandler(ch) self.log.addHandler(fh) ch_fmt = logging.Formatter("%(message)s") fh_fmt = logging.Formatter("%(asctime)s %(process)d (%(levelname)s)\t: %(message)s") ch.setFormatter(ch_fmt) fh.setFormatter(fh_fmt) logging_level = {'DEBUG': logging.DEBUG, 'INFO' : logging.INFO} self.log.setLevel(logging_level[self.debug_level]) def debug(self, msg): if self.debug_level == 'DEBUG': self.log.debug("[.cas.][debug] :: %s" % (msg,)) def status(self, msg): """ function to print status messages """ sys.stdout.write("[.cas.] :: " + msg + "\r") sys.stdout.flush() def info(self, msg): """ function to print procedure """ self.log.info("[.cas.] :: %s" % (msg,)) class UtilException(Exception): pass class UtilBase(object): def regexFindall(self, regex, string): ''' Return a list of all non overlapping matches in the string(s) ''' out=[] reg=re.compile(regex, re.MULTILINE) for i in reg.findall(string): out.append(i) if len(out): return out return False def regexSearch(self, regex, string): reg=re.compile(regex, re.MULTILINE) try: return reg.search(string).group() except: return False def directoryList(self, filepath): """ file listing with symlink support """ for root, dirs, files in os.walk(filepath): yield root, dirs, files for dir in dirs: dirpath = os.path.join(root, dir) if os.path.islink(dirpath): for val in self.directoryList(dirpath): yield val def make_exe(self, fn): ''' make fn executable ''' if os.name == 'posix': oldmode = os.stat(fn).st_mode & 07777 newmode = (oldmode | 0555) & 07777 os.chmod(fn, newmode) return def save(self, obj, fname): ''' push data to pickle ''' FILE=open(fname, 'w') cPickle.dump(obj, FILE) FILE.close() return def load(self, fname): ''' grab data from pickle file ''' if os.path.isfile(fname): FILE=open(fname, 'r') out=cPickle.load(FILE) FILE.close() else: raise UtilException("%s : Unable to locate/load file." % (fname,)) return out def getElfArch(self, debug): """ determine machine type for ELF file """ supportArch = {"IBM S/390":"s390x", "Intel 80386":"i686", "Advanced Micro Devices X86-64" : "x86_64", "Intel IA-64": "ia64", "PowerPC64": "ppc64"} # readelf pulls in various information about elf object files # we only care about data in the elf header at the start of file # more specifically the machine type cmd = ["readelf", "-h", debug] cmd2 = ["grep", "Machine"] pipe = Popen(cmd, stdout=PIPE, stderr=PIPE) pipe2 = Popen(cmd2, stdin=pipe.stdout, stdout=PIPE, stderr=PIPE).communicate() machine, sts = pipe2 for k, v in supportArch.iteritems(): if k in machine: return supportArch[k] return False def buildCrashFile(self, dst, vmcore, debug, file_in="crash.in", crash_bin="/usr/bin/crash"): """ build crash and crash.in file with output from the snippets in /var/lib/cas/snippets """ # TODO: We should provide the environment variables mentioned in the # template snippet, CAS_ARCH, CAS_KERNEL, CAS_SIZE, and whatever else # makse sense so scripts can opt in based on the environmentals dir_listing=[] crashInputCmds=[] for root, dirs, files in os.walk("/var/lib/cas/snippets/"): for name in files: dir_listing.append(os.path.join(root, name)) for a in dir_listing: crashInputCmds.append(Popen(a, stdout=PIPE).communicate()[0]) crashInputCmds.append("exit\n") # Build crash input file crashInputPath = os.path.join(dst, file_in) crashInputFH = open(crashInputPath, "w") crashInputFH.write("".join(crashInputCmds)) crashInputFH.close() vmcorePath = os.path.join(dst, vmcore) crashCmd = "#!/bin/sh\n%s %s %s $*\n" % (crash_bin, vmcorePath, debug ) crashExe = os.path.join(dst,"crash") fh = open(crashExe,"w") fh.write(crashCmd) fh.close() self.make_exe(crashExe) return