import os import unittest from oeqa.oetest import oeRuntimeTest from oeqa.utils.decorators import * #in the future these lists could be moved outside of module errors = ["error", "cannot", "can\'t", "failed"] common_errors = [ '(WW) warning, (EE) error, (NI) not implemented, (??) unknown.', 'dma timeout', 'can\'t add hid device:', 'usbhid: probe of ', ] x86_common = [ '[drm:psb_do_init] *ERROR* Debug is', 'wrong ELF class', 'Could not enable PowerButton event', 'probe of LNXPWRBN:00 failed with error -22', ] + common_errors qemux86_common = [ 'Fast TSC calibration', '_OSC failed (AE_NOT_FOUND); disabling ASPM', 'Open ACPI failed (/var/run/acpid.socket) (No such file or directory)', 'Failed to load module "vesa"', 'Failed to load module "modesetting"', 'Failed to load module "glx"', 'wrong ELF class', ] + common_errors ignore_errors = { 'default' : common_errors, 'qemux86' : [ 'Failed to access perfctr msr (MSR c1 is 0)', "fail to add MMCONFIG information, can't access extended PCI configuration space under this bridge.", ] + qemux86_common, 'qemux86-64' : qemux86_common, 'qemumips' : [ 'Failed to load module "glx"', ] + common_errors, 'qemuppc' : [ 'PCI 0000:00 Cannot reserve Legacy IO [io 0x0000-0x0fff]', 'mode "640x480" test failed', 'Failed to load module "glx"', ] + common_errors, 'qemuarm' : [ 'mmci-pl18x: probe of fpga:05 failed with error -22', 'mmci-pl18x: probe of fpga:0b failed with error -22', 'Failed to load module "glx"' ] + common_errors, 'emenlow' : x86_common, 'crownbay' : x86_common, 'genericx86' : x86_common, 'genericx86-64' : x86_common, } log_locations = ["/var/log/","/var/log/dmesg", "/tmp/dmesg_output.log"] class ParseLogsTest(oeRuntimeTest): @classmethod def setUpClass(self): self.errors = errors self.ignore_errors = ignore_errors self.log_locations = log_locations self.msg = "" def getMachine(self): (status, output) = self.target.run("uname -n") return output #get some information on the CPU of the machine to display at the beginning of the output. This info might be useful in some cases. def getHardwareInfo(self): hwi = "" (status, cpu_name) = self.target.run("cat /proc/cpuinfo | grep \"model name\" | head -n1 | awk 'BEGIN{FS=\":\"}{print $2}'") (status, cpu_physical_cores) = self.target.run("cat /proc/cpuinfo | grep \"cpu cores\" | head -n1 | awk {'print $4'}") (status, cpu_logical_cores) = self.target.run("cat /proc/cpuinfo | grep \"processor\" | wc -l") (status, cpu_arch) = self.target.run("uname -m") hwi += "Machine information: \n" hwi += "*******************************\n" hwi += "Machine name: "+self.getMachine()+"\n" hwi += "CPU: "+str(cpu_name)+"\n" hwi += "Arch: "+str(cpu_arch)+"\n" hwi += "Physical cores: "+str(cpu_physical_cores)+"\n" hwi += "Logical cores: "+str(cpu_logical_cores)+"\n" hwi += "*******************************\n" return hwi #go through the log locations provided and if it's a folder create a list with all the .log files in it, if it's a file just add #it to that list def getLogList(self, log_locations): logs = [] for location in log_locations: (status, output) = self.target.run("test -f "+str(location)) if (status == 0): logs.append(str(location)) else: (status, output) = self.target.run("test -d "+str(location)) if (status == 0): (status, output) = self.target.run("find "+str(location)+"/*.log -maxdepth 1 -type f") output = output.splitlines() for logfile in output: logs.append(os.path.join(location,str(logfile))) return logs #build the grep command to be used with filters and exclusions def build_grepcmd(self, errors, ignore_errors, log): grepcmd = "grep " grepcmd +="-Ei \"" for error in errors: grepcmd += error+"|" grepcmd = grepcmd[:-1] grepcmd += "\" "+str(log)+" | grep -Eiv \'" try: errorlist = ignore_errors[self.getMachine()] except KeyError: self.msg += "No ignore list found for this machine, using default\n" errorlist = ignore_errors['default'] for ignore_error in errorlist: ignore_error = ignore_error.replace("(", "\(") ignore_error = ignore_error.replace(")", "\)") ignore_error = ignore_error.replace("'", ".") ignore_error = ignore_error.replace("?", "\?") ignore_error = ignore_error.replace("[", "\[") ignore_error = ignore_error.replace("]", "\]") ignore_error = ignore_error.replace("*", "\*") grepcmd += ignore_error+"|" grepcmd = grepcmd[:-1] grepcmd += "\'" return grepcmd #grep only the errors so that their context could be collected. Default context is 10 lines before and after the error itself def parse_logs(self, errors, ignore_errors, logs, lines_before = 10, lines_after = 10): results = {} rez = [] for log in logs: thegrep = self.build_grepcmd(errors, ignore_errors, log) try: (status, result) = self.target.run(thegrep) except: pass if result: results[log] = {} rez = result.splitlines() for xrez in rez: command = "grep \"\\"+str(xrez)+"\" -B "+str(lines_before)+" -A "+str(lines_after)+" "+str(log) try: (status, yrez) = self.target.run(command) except: pass results[log][xrez]=yrez return results #get the output of dmesg and write it in a file. This file is added to log_locations. def write_dmesg(self): (status, dmesg) = self.target.run("dmesg") (status, dmesg2) = self.target.run("echo \""+str(dmesg)+"\" > /tmp/dmesg_output.log") @skipUnlessPassed('test_ssh') def test_parselogs(self): self.write_dmesg() log_list = self.getLogList(self.log_locations) result = self.parse_logs(self.errors, self.ignore_errors, log_list) print self.getHardwareInfo() errcount = 0 for log in result: self.msg += "Log: "+log+"\n" self.msg += "-----------------------\n" for error in result[log]: errcount += 1 self.msg += "Central error: "+str(error)+"\n" self.msg += "***********************\n" self.msg += result[str(log)][str(error)]+"\n" self.msg += "***********************\n" self.msg += "%s errors found in logs." % errcount self.assertEqual(errcount, 0, msg=self.msg)