204 lines
7.9 KiB
Python
204 lines
7.9 KiB
Python
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 ",
|
|
"_OSC failed (AE_ERROR)",
|
|
"_OSC failed (AE_SUPPORT)",
|
|
"AE_ALREADY_EXISTS"
|
|
"ACPI _OSC request failed (AE_SUPPORT)"
|
|
"can\'t disable ASPM",
|
|
"Failed to load module \"vesa\"",
|
|
"Failed to load module vesa",
|
|
"Failed to load module \"modesetting\"",
|
|
"Failed to load module modesetting",
|
|
"Failed to load module \"glx\"",
|
|
"Failed to load module glx",
|
|
"[drm] Cannot find any crtc or sizes - going 1024x768"
|
|
]
|
|
|
|
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)',
|
|
'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"',
|
|
'pci 0000:00:00.0: [Firmware Bug]: reg 0x..: invalid BAR (can\'t size)',
|
|
] + common_errors,
|
|
'qemuppc' : [
|
|
'PCI 0000:00 Cannot reserve Legacy IO [io 0x0000-0x0fff]',
|
|
'host side 80-wire cable detection failed, limiting max speed',
|
|
'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,
|
|
'edgerouter' : [
|
|
'Fatal server error:',
|
|
] + common_errors,
|
|
'minnow' : [
|
|
'netlink init failed',
|
|
'NETLINK INITIALIZATION FAILED',
|
|
] + common_errors,
|
|
'jasperforest' : [
|
|
'Activated service \'org.bluez\' failed:',
|
|
'Unable to find NFC netlink family',
|
|
'netlink init failed',
|
|
'NETLINK INITIALIZATION FAILED',
|
|
] + common_errors,
|
|
}
|
|
|
|
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")
|
|
if (status == 0):
|
|
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)
|